c# - ElasticSearch 匹配 int 和 string 列表
问题描述
我对 ElasticSearch 相当陌生,我正在尝试对我们的类别页面进行查询,ES 返回的每个产品都在该类别中。出于某种原因,它包括该类别之外的产品,我似乎无法弄清楚为什么。
产品是基本产品,包含一个类别 ID 列表(产品可以属于多个类别)。除了在 categoryId 上进行匹配外,它还应该在产品名称和变体的详细描述中进行搜索。
public IReadOnlyCollection<Product> GetByCategory(string value, int take, int categoryId)
{
value = string.Format("*{0}*", value);
var query = new SearchDescriptor<Product>()
.Index(this.index)
.Query(q => q
.Bool(b => b
.Must(s => s
.Match(m => m
.Field(ff => ff
.AttachedCategoryIds.Contains(categoryId)
)
)
)
.Must(s => s
.QueryString(m => m
.Query(value)
.Fields(ff => ff
.Field(f => f.Name)
.Field(f => f.Variants.Select(input => input.LongDescription))
)
.Type(TextQueryType.CrossFields)
)
)
)
)
.Size(take)
.Sort(ss => ss.Descending(SortSpecialField.Score));
var data = client.Search<Product>(query);
var products = data.Documents;
return products;
}
我希望只从弹性中获取当前类别中的产品,但由于某种原因,它给了我不属于某个类别/不同类别的产品。
解决方案
您的查询不正确。假设以下 POCO
public class Product
{
public string Name { get; set; }
public List<Variant> Variants { get; set; }
public List<int> AttachedCategoryIds { get; set; }
}
public class Variant
{
public string LongDescription { get; set; }
}
查询将类似于
var index = "index_name";
var categoryId = 1;
var value = "this is the query";
var take = 20;
var query = new SearchDescriptor<Product>()
.Index(index)
.Query(q => q
.Bool(b => b
.Must(s => s
.QueryString(m => m
.Query(value)
.Fields(ff => ff
.Field(f => f.Name)
.Field(f => f.Variants.First().LongDescription)
)
.Type(TextQueryType.CrossFields)
)
)
.Filter(f => f
.Term(ff => ff.AttachedCategoryIds, categoryId)
)
)
)
.Size(take)
.Sort(ss => ss.Descending(SortSpecialField.Score));
var searchResponse = client.Search<Product>(query);
几点
.Field(f => f.Variants.First().LongDescription)
是一个表达式,它将解析为将在 JSON 中序列化以定位 Elasticsearch 中的字段的字符串。在这种情况下,这将解决"variants.longDescription"
term
查询可用于确定 Elasticsearch 中的字段是否包含特定值。我已将查询放入bool
查询过滤器子句中,因为我认为您不想为查询的这一部分计算相关性分数,即文档要么在字段中包含术语,要么没有。
这序列化为以下查询
POST http://localhost:9200/index_name/product/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"attachedCategoryIds": {
"value": 1
}
}
}
],
"must": [
{
"query_string": {
"fields": [
"name",
"variants.longDescription"
],
"query": "this is the query",
"type": "cross_fields"
}
}
]
}
},
"size": 20,
"sort": [
{
"_score": {
"order": "desc"
}
}
]
}
此查询假设Variants
onProduct
被映射为object
数据类型。它可以更简洁地写成
var query = new SearchDescriptor<Product>()
.Index(index)
.Query(q => q
.QueryString(m => m
.Query(value)
.Fields(ff => ff
.Field(f => f.Name)
.Field(f => f.Variants.First().LongDescription)
)
.Type(TextQueryType.CrossFields)
) && +q
.Term(ff => ff.AttachedCategoryIds, categoryId)
)
.Size(take)
.Sort(ss => ss.Descending(SortSpecialField.Score));
推荐阅读
- python - 将字典项添加到列表并将具有相同键的值附加到较新的列表项
- robotframework - 库中的机器人框架关键字名称更改
- gruntjs - Grunt wont watch less
- serverless-framework - serverless framework and use key management service (KMS)
- c# - URI 中的版本不受支持的 API 版本——出了什么问题?
- ruby-on-rails - 提交表单时弹出/模态框,取决于表单中输入了什么信息
- html - How to use image inside a div without moving the other elements
- sql - How to handle getting a list of unique customers per product grouping
- python-3.x - How to train/extend an nltk vocabulary in a non-English language
- amazon-web-services - How to generate ListnerCertificate CertificateArn in loadbalancer