[英]C# NEST Elastic Search Query Multiple Conditions
我正在做一些測試來改變我的架構。 我們要刪除MongoDB並改用ElasticSearch。 但是我真的不了解這項技術。 我正在使用NEST作為驅動程序,並且無法翻譯過去用於mongo的查詢。
public async Task<IEnumerable<Keyword>> GetKeywordsAsync(string prefix, int startIndex, int totalItems, int minimumTotalSearch, CancellationToken cancellationToken)
{
return await _mongoReader.GetEntitiesAsync<KeywordEntity, Keyword>(CollectionName,
queryable =>
queryable.Where(entity => entity.KeywordName.StartsWith(prefix) && entity.TotalSearch >= minimumTotalSearch)
.OrderBy(entity => entity.KeywordName)
.Select(_keywordConverter.GetConverter())
.Skip(startIndex)
.Take(totalItems),
cancellationToken).ConfigureAwait(false);
}
public async Task<IEnumerable<TModel>> GetEntitiesAsync<TDocument, TModel>(string collectionName,
Func<IMongoQueryable<TDocument>, IMongoQueryable<TModel>> getQueryable,
CancellationToken cancellationToken)
{
var documents = GetDocuments<TDocument>(collectionName);
var query = getQueryable(documents.AsQueryable());
return await query.ToListAsync(cancellationToken).ConfigureAwait(false);
}
這是我為ElasticSearch做出的一個簡單發現:
public async Task<IEnumerable<TModel>> FindAsync<TModel, TValue>(string index,
Expression<Func<TModel, TValue>> findExpression, TValue value, int limit,
CancellationToken cancellationToken) where TModel : class
{
var searchRequest = new SearchRequest<TModel>(index)
{
Query =
Query<TModel>.Match(
a => a.Field(findExpression).Query(string.Format(CultureInfo.InvariantCulture, "{0}", value))),
Size = limit
};
var resGet = await _elasticClientFactory.Create().SearchAsync<TModel>(searchRequest, cancellationToken).ConfigureAwait(false);
return resGet?.Documents;
}
問題是我無法在Elastic中翻譯查詢Mongo ...
這很痛苦,但這是彈性查詢:
{
"query": {
"bool": {
"must": [
{"range" : { "totalSearch" : { "gte" : minimumTotalSearch }}},
{"prefix": { "keywordName": prefix}}
]
}
},
"from": startIndex,
"size": totalItems
}
->解決方案:經過一些艱苦的編碼,我找到了一種在C#中進行查詢的方法:
var result =
ecf.Create()
.Search<KeywordEntity>(
a => a.Query(
z =>
z.Bool(
e =>
e.Must(r => r.Range(t => t.Field(y => y.TotalSearch).GreaterThanOrEquals(minimumTotalSearch)),
t => t.Prefix(y => y.KeywordName, prefix)))).Index("keywords"));
但是現在我要問自己這是否是執行此查詢的最佳方法(無需跳過/接聽就很容易了)。 作為我的新手,也許有一個更優化的查詢...
您的解決方案看起來不錯,但是有兩點值得強調。
range
查詢查找匹配的文檔或不匹配的文檔,即它是不需要對匹配文檔進行評分的謂詞,因此range
查詢可以包裝在bool
查詢filter
子句中; 這些子句可以由Elasticsearch使用咆哮的位圖進行緩存。 NEST還將QueryContainer
(根查詢類型)上的運算符超載,以QueryContainer
運算符,以合並它們以構建bool
查詢。 然后,您的解決方案將成為(具有上述建議)
var searchResponse = client.Search<KeywordEntity>(s => s
.Index("keywords")
.Query(q => q
.Prefix(p => p.KeywordName, prefix) && +q
.Range(r => r
.Field(y => y.TotalSearch)
.GreaterThanOrEquals(minimumTotalSearch)
)
)
);
可以使用分頁.From()
和.Size()
別名與.Skip()
和.Take()
分別地),以及僅指定部分集的字段是從使用源返回的源過濾 。 一個更完整的例子是
var client = new ElasticClient();
var minimumTotalSearch = 10;
var prefix = "prefix";
var startIndex = 10;
var totalItems = 10;
var searchResponse = client.Search<KeywordEntity>(s => s
.Index("keywords")
.Query(q => q
.Prefix(p => p.KeywordName, prefix) && +q
.Range(r => r
.Field(y => y.TotalSearch)
.GreaterThanOrEquals(minimumTotalSearch)
)
)
// source filtering
.Source(sf => sf
.Includes(f => f
.Fields(
ff => ff.KeywordName,
ff => ff.TotalSearch
)
)
)
// sorting. By default, documents will be sorted by _score descending
.Sort(so => so
.Ascending(a => a.KeywordName)
)
// skip x documents
.Skip(startIndex)
// take next y documents
.Take(totalItems)
);
這將建立查詢
{
"from": 10,
"size": 10,
"sort": [
{
"keywordName": {
"order": "asc"
}
}
],
"_source": {
"includes": [
"keywordName",
"totalSearch"
]
},
"query": {
"bool": {
"must": [
{
"prefix": {
"keywordName": {
"value": "prefix"
}
}
}
],
"filter": [
{
"range": {
"totalSearch": {
"gte": 10.0
}
}
}
]
}
}
}
最后一件事:)因為在您的Mongo查詢中,您是按前綴升序進行排序的,所以您還可以通過在bool
查詢中同時使其成為filter
子句來放棄對Elasticsearch查詢中的prefix
查詢評分。
查詢將是這樣的。
client.Search<KeywordEntity>(s => s.Index("<INDEX NAME>")
.Type("<TYPE NAME>")
.Query(q =>q
.Bool(b => b.
Must(prefix => prefix.Prefix(pre => pre.OnField("KeywordName").Value("PREFIX QUERY")))
.Must(range => range.Range(ran => ran.OnField("TotalSearch").GreaterOrEquals(minimumTotalSearch)))
)).SortAscending("KeywordName")
.From(StartIndex)
.Size(totalItems));
如果您有任何困難,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.