搜索Elasticsearch中的文档
该应用程序使用ElasticsearchCRUD访问Elasticsearch。 API可以使用任何DTO或实体类,并将其自动映射到Elasticsearch索引并使用类类型键入。 默认索引是类的类型,所有字符都转换为小写字符。 默认类型是小写字符的类型名称。 如果Elasticsearch需要不同的映射,这可以很容易地改变。 例如,在Elasticsearch中保存为子文档的类需要其索引的映射,即。 使用存储父文档的索引。
在这个例子中使用了一个Skill 类。 这个类被保存在搜索引擎中,具有索引skills
和类型skill
。
public class Skill
{
[Required]
[Range(1, long.MaxValue)]
public long Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public DateTimeOffset Created { get; set; }
public DateTimeOffset Updated { get; set; }
}
ElasticsearchCRUD Search方法用于使用QueryString进行全文搜索。 该方法从SearchController
获取 term(s),并在引擎中执行QueryString搜索。 此搜索不区分大小写。
您可以使用context.Search
方法几乎可以进行任何搜索,而不仅仅是查询字符串搜索。 不支持高亮显示的结果,不支持多个索引或多个类型搜索。 所有您需要做的是为搜索构建JSON查询,并从匹配中返回类型的集合。 查询是使用Search
类构建的。 Query
属性定义可以使用通配符的查询字符串搜索。
public IEnumerable<Skill> QueryString(string term)
{
var results = _context.Search<Skill>(BuildQueryStringSearch(term));
return results.PayloadResult.Hits.HitsResult.Select(t => t.Source);
}
private ElasticsearchCRUD.Model.SearchModel.Search BuildQueryStringSearch(string term)
{
var names = "";
if (term != null)
{
names = term.Replace("+", " OR *");
}
var search = new ElasticsearchCRUD.Model.SearchModel.Search
{
Query = new Query(new QueryStringQuery(names + "*"))
};
return search;
}
搜索方法用于MVC SearchController
。 Json
被返回,因为jQuery Autocomplete 控件使用了action方法。
public JsonResult Search(string term)
{
return Json(_searchProvider.QueryString(term), "Skills", JsonRequestBehavior.AllowGet);
}
Autocomplete(jquery-ui)源方法使用SearchController
中的操作方法搜索。 这将对象数组保存到autocomplete控件。 此控件需要控件的每个项中的标签和值属性。 select方法用于从搜索中选择一个结果。 然后将所选项目添加到页面上的其他html控件,以更新或删除HTTP请求。
<fieldset class="form">
<legend>SEARCH for a document in the search engine</legend>
<table width="500">
<tr>
<th></th>
</tr>
<tr>
<td>
<label for="autocomplete">Search: </label>
</td>
</tr>
<tr>
<td>
<input id="autocomplete" type="text" style="width:500px" />
</td>
</tr>
</table>
</fieldset>
@section scripts
{
<script type="text/javascript">
var items;
$(document).ready(function() {
$("input#autocomplete").autocomplete({
source: function(request, response) {
$.ajax({
url: "search",
dataType: "json",
data: {
term: request.term,
},
success: function(data) {
var itemArray = new Array();
for (i = 0; i < data.length; i++) {
itemArray[i] = { label: data[i].Name, value: data[i].Name, data: data[i] }
}
console.log(itemArray);
response(itemArray);
},
error: function(data, type) {
console.log(type);
}
});
},
select: function (event, ui) {
$("#spanupdateId").text(ui.item.data.Id);
$("#spanupdateCreated").text(new Date(parseInt(ui.item.data.Created.substr(6))));
$("#spanupdateUpdated").text(new Date(parseInt(ui.item.data.Updated.substr(6))));
$("#updateName").text(ui.item.data.Name);
$("#updateDescription").text(ui.item.data.Description);
$("#updateName").val(ui.item.data.Name);
$("#updateDescription").val(ui.item.data.Description);
$("#updateId").val(ui.item.data.Id);
$("#updateCreated").val(ui.item.data.Created);
$("#updateUpdated").val(ui.item.data.Updated);
$("#spandeleteId").text(ui.item.data.Id);
$("#deleteId").val(ui.item.data.Id);
$("#deleteName").text(ui.item.data.Name);
console.log(ui.item);
}
});
});
</script>
}
然后可以使用以下控件:
Elasticsearch创建,更新和删除
为了方便搜索和提供一些数据,使用ElasticsearchCRUD添加了创建,更新和删除实现。 提供者使用ElasticsearchCRUD的上下文,并在一个批量请求中执行所有待处理的更改到Elasticsearch。 多个索引,类型可以在单个上下文中执行批量请求。 HttpClient
类在上下文中心下使用。 在Elasticsearch中添加或更改大量数据时,效果很好。
private const string ConnectionString = "http://localhost:9200/";
private readonly IElasticsearchMappingResolver _elasticsearchMappingResolver = new ElasticsearchMappingResolver();
public void AddUpdateEntity(Skill skill)
{
using (var context = new ElasticsearchContext(ConnectionString, _elasticsearchMappingResolver))
{
context.AddUpdateDocument(skill, skill.Id);
context.SaveChanges();
}
}
public void UpdateSkill(long updateId, string updateName, string updateDescription)
{
using (var context = new ElasticsearchContext(ConnectionString, _elasticsearchMappingResolver))
{
var skill = context.GetDocument<Skill>(updateId);
skill.Updated = DateTime.UtcNow;
skill.Name = updateName;
skill.Description = updateDescription;
context.AddUpdateDocument(skill, skill.Id);
context.SaveChanges();
}
}
public void DeleteSkill(long deleteId)
{
using (var context = new ElasticsearchContext(ConnectionString, _elasticsearchMappingResolver))
{
context.DeleteDocument<Skill>(deleteId);
context.SaveChanges();
}
}
这可以在SearchController中使用。 HTTP Post Index操作方法中的创建skill文档已经实现了验证。 这调用ElasticsearchCRUD的AddUpdateDocument方法。 如果搜索引擎中已存在具有相同ID的文档,则文档将被覆盖。 通常实体来自主数据库,并保存elasticsearch以进行最佳搜索。 主数据库管理该实体的Ids,因此这不是该用例的问题。
readonly ISearchProvider _searchProvider = new ElasticSearchProvider();
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Skill model)
{
if (ModelState.IsValid)
{
model.Created = DateTime.UtcNow;
model.Updated = DateTime.UtcNow;
_searchProvider.AddUpdateDocument(model);
return Redirect("Search/Index");
}
return View("Index", model);
}
[HttpPost]
public ActionResult Update(long updateId, string updateName, string updateDescription)
{
_searchProvider.UpdateSkill(updateId, updateName, updateDescription);
return Redirect("Index");
}
[HttpPost]
public ActionResult Delete(long deleteId)
{
_searchProvider.DeleteSkill(deleteId);
return Redirect("Index");
}
然后可以在视图中使用控制器。 视图有3种不同的形式:创建,删除和更新。 当从Autocomplete控件中选择搜索结果时,删除和更新表单将被更新。
<form name="input" action="update" method="post">
<fieldset class="form">
<legend>UPDATE an existing document in the search engine</legend>
<table width="500">
<tr>
<th></th>
<th></th>
</tr>
<tr>
<td>
<span>Id:</span>
</td>
<td>
<span id="spanupdateId">-</span>
<input id="updateId" name="updateId" type="hidden" />
</td>
</tr>
<tr>
<td>
<span>Name:</span>
</td>
<td>
<input id="updateName" name="updateName" type="text" />
</td>
</tr>
<tr>
<td>
<span>Description:</span>
</td>
<td>
<input id="updateDescription" name="updateDescription" type="text" />
</td>
</tr>
<tr>
<td>
<span>Created:</span>
</td>
<td>
<span id="spanupdateCreated">-</span>
<input id="updateCreated" name="updateCreated" type="hidden" />
</td>
</tr>
<tr>
<td>
<span>Updated:</span>
</td>
<td>
<span id="spanupdateUpdated">-</span>
<input id="updateUpdated" name="updateUpdated" type="hidden" />
</td>
</tr>
<tr>
<td>
<br />
<input type="submit" value="Update Skill" style="width: 200px" />
</td>
<td></td>
</tr>
</table>
</fieldset>
</form>
<form name="input" action="delete" method="post">
<fieldset class="form">
<legend>DELETE an existing document in the search engine</legend>
<table width="500">
<tr>
<th></th>
<th></th>
</tr>
<tr>
<td>
<span id="deleteName">-</span>
</td>
<td>
<span id="spandeleteId">-</span>
<input id="deleteId" name="deleteId" type="hidden" />
</td>
</tr>
<tr>
<td>
<br />
<input type="submit" value="Delete Skill" style="width: 200px" />
</td>
<td></td>
</tr>
</table>
</fieldset>
</form>
@using (Html.BeginForm("Index", "Search"))
{
@Html.ValidationSummary(true)
<fieldset class="form">
<legend>CREATE a new document in the search engine</legend>
<table width="500">
<tr>
<th></th>
<th></th>
</tr>
<tr>
<td>
@Html.Label("Id:")
</td>
<td>
@Html.EditorFor(model => model.Id)
@Html.ValidationMessageFor(model => model.Id)
</td>
</tr>
<tr>
<td>
@Html.Label("Name:")
</td>
<td>
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</td>
</tr>
<tr>
<td>
@Html.Label("Description:")
</td>
<td>
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</td>
</tr>
<tr>
<td>
<br />
<input type="submit" value="Add Skill" style="width:200px" />
</td>
<td></td>
</tr>
</table>
</fieldset>
}
然后可以在浏览器中使用该应用程序,如下所示:
结论
正如你所看到的,使用具有Elasticsearch的ASP.NET MVC进行全文搜索是非常容易的。 这可以很容易地改变为使用Web API与Angular JS。 由于这些规模很好,性能很好,您可以将其用于几乎任何应用程序。