我正在做一些测试来改变我的架构。我们想要删除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
}
- &GT;方案: 经过一些斗争编码后,我找到了一种在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"));
但现在我问自己这是否是进行此查询的最佳方式(没有跳过/接受这很容易)。因为我是新的,可能有更优化的查询...
答案 0 :(得分:1)
您的解决方案看起来不错,但有几点值得强调。
range
查询找到匹配或不匹配的文档,即它是不需要对匹配文档进行评分的谓词,因此range
查询可以包含在{bool
中。 1}} query 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查询中,您按前缀升序排序,您还可以放弃在Elasticsearch查询中对prefix
查询进行评分,同时将其作为filter
子句bool
查询。
答案 1 :(得分:0)
查询将是这样的。
// object for refering text
var obj = {};
// get all tr except the first one which holds header
$('table tr:not(:first-child)').filter(function() {
// get td contents and trim out space
var txt = $('td:last-child', this).text().trim();
// check already defined in object or not
if (txt in obj)
// if defined return true, it's dupe
return true;
// else define the property
obj[txt] = true;
// add class to filtered tr
}).addClass('dup')
如果您发现任何困难,请告诉我。