gpt4 book ai didi

C# NEST Elastic Search 查询多个条件

转载 作者:行者123 更新时间:2023-12-03 01:48:33 25 4
gpt4 key购买 nike

我正在做一些测试来改变我的架构。我们想放弃 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 中翻译我的 Query 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 可以使用 roaring bitmaps 缓存这些子句.

  • NEST 还重载了 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() 别名),以及使用 source filtering 指定仅从源返回的部分字段集.一个更完整的例子是
    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 查询中,您按前缀升序排序,您也可以放弃对 prefix 进行评分通过将 Elasticsearch 查询中的查询也设为 filter bool 中的子句询问。

    关于C# NEST Elastic Search 查询多个条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42141793/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com