Elasticsearch嵌套数组的多个过滤条件
Elasticsearch multiple filter conditions for nested array
这个问题可能在某处得到了回答,但我找不到。所以我寻求帮助
我的产品模型有一个嵌套的属性列表。像这样
[
{
ID: "Product1",
...
Properties: [
{ "Source": "Color", Value: "green"},
{ "Source": "Size", Value: "2"},
]
},
{
ID: "Product2",
...
Properties: [
{ "Source": "Color", Value: "blue"},
{ "Source": "Size", Value: "2"},
]
},
{
ID: "Product3",
....
Properties: [
{ "Source": "Color", Value: "red"},
{ "Source": "Size", Value: "1"},
]
},
]
索引映射:
"properties" : {
"type" : "nested",
"properties" : {
"source" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"value" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
而且我需要我的搜索查询来仅查找颜色为绿色或蓝色且尺寸为 2 的产品。
我为我的搜索请求创建了这个查询,但它会return一个空结果。
new Nest.NestedQuery
{
Path = new Nest.Field("properties"),
Query = new Nest.BoolQuery() {
Must = new Nest.QueryContainer[] {
new Nest.BoolQuery()
{
Must = new Nest.QueryContainer[] {
new Nest.TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Color"
},
new Nest.TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] { "green", "blue"}
}
}
}
},
new Nest.BoolQuery()
{
Must = new Nest.QueryContainer[] {
new Nest.TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Size"
},
new Nest.TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] { "2"}
}
}
}
}
}
}
你能帮我构建这种查询我用错了什么吗?
谢谢
尝试用嵌套查询包装每个 must 子句:
var query = new BoolQuery
{
Must = new QueryContainer[]
{
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Color"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] { "green", "blue"}
}
}
}
},
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Size"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] {"2"}
}
}
}
}
}
};
完整的工作示例
class Program
{
public class Document
{
public int Id { get; set; }
[Nested]
public List<Property> Properties { get; set; }
}
public class Property
{
public string Source { get; set; }
public string Value { get; set; }
public override string ToString() => $"Source: {Source} Value: {Value}";
}
static async Task Main(string[] args)
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(pool);
connectionSettings.DefaultIndex("documents");
connectionSettings.DisableDirectStreaming();
connectionSettings.PrettyJson();
var client = new ElasticClient(connectionSettings);
var deleteIndexResponse = await client.Indices.DeleteAsync("documents");
var createIndexResponse = await client.Indices.CreateAsync("documents", d => d
.Map(m => m.AutoMap<Document>()));
var indexDocument = await client
.IndexDocumentAsync(new Document
{
Id = 1,
Properties = new List<Property>
{
new Property {Source = "Color", Value = "green"},
new Property {Source = "Size", Value = "2"},
}
});
indexDocument = await client
.IndexDocumentAsync(new Document
{
Id = 2,
Properties = new List<Property>
{
new Property {Source = "Color", Value = "blue"},
new Property {Source = "Size", Value = "2"},
}
});
indexDocument = await client
.IndexDocumentAsync(new Document
{
Id = 3,
Properties = new List<Property>
{
new Property {Source = "Color", Value = "red"},
new Property {Source = "Size", Value = "1"},
}
});
var refreshAsync = client.Indices.RefreshAsync();
var query = new BoolQuery
{
Must = new QueryContainer[]
{
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Color"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] {"green", "blue"}
}
}
}
},
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Size"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] {"2"}
}
}
}
}
}
};
var response = client.Search<Document>(s => s.Query(q => query));
foreach (var document in response.Documents)
{
Console.WriteLine($"Id: {document.Id}");
document.Properties.ForEach(Console.WriteLine);
Console.WriteLine();
}
}
}
打印:
Id: 1
Source: Color Value: green
Source: Size Value: 2
Id: 2
Source: Color Value: blue
Source: Size Value: 2
希望对您有所帮助。
这个问题可能在某处得到了回答,但我找不到。所以我寻求帮助 我的产品模型有一个嵌套的属性列表。像这样
[
{
ID: "Product1",
...
Properties: [
{ "Source": "Color", Value: "green"},
{ "Source": "Size", Value: "2"},
]
},
{
ID: "Product2",
...
Properties: [
{ "Source": "Color", Value: "blue"},
{ "Source": "Size", Value: "2"},
]
},
{
ID: "Product3",
....
Properties: [
{ "Source": "Color", Value: "red"},
{ "Source": "Size", Value: "1"},
]
},
]
索引映射:
"properties" : {
"type" : "nested",
"properties" : {
"source" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"value" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
而且我需要我的搜索查询来仅查找颜色为绿色或蓝色且尺寸为 2 的产品。
我为我的搜索请求创建了这个查询,但它会return一个空结果。
new Nest.NestedQuery
{
Path = new Nest.Field("properties"),
Query = new Nest.BoolQuery() {
Must = new Nest.QueryContainer[] {
new Nest.BoolQuery()
{
Must = new Nest.QueryContainer[] {
new Nest.TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Color"
},
new Nest.TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] { "green", "blue"}
}
}
}
},
new Nest.BoolQuery()
{
Must = new Nest.QueryContainer[] {
new Nest.TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Size"
},
new Nest.TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] { "2"}
}
}
}
}
}
}
你能帮我构建这种查询我用错了什么吗? 谢谢
尝试用嵌套查询包装每个 must 子句:
var query = new BoolQuery
{
Must = new QueryContainer[]
{
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Color"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] { "green", "blue"}
}
}
}
},
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Size"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] {"2"}
}
}
}
}
}
};
完整的工作示例
class Program
{
public class Document
{
public int Id { get; set; }
[Nested]
public List<Property> Properties { get; set; }
}
public class Property
{
public string Source { get; set; }
public string Value { get; set; }
public override string ToString() => $"Source: {Source} Value: {Value}";
}
static async Task Main(string[] args)
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(pool);
connectionSettings.DefaultIndex("documents");
connectionSettings.DisableDirectStreaming();
connectionSettings.PrettyJson();
var client = new ElasticClient(connectionSettings);
var deleteIndexResponse = await client.Indices.DeleteAsync("documents");
var createIndexResponse = await client.Indices.CreateAsync("documents", d => d
.Map(m => m.AutoMap<Document>()));
var indexDocument = await client
.IndexDocumentAsync(new Document
{
Id = 1,
Properties = new List<Property>
{
new Property {Source = "Color", Value = "green"},
new Property {Source = "Size", Value = "2"},
}
});
indexDocument = await client
.IndexDocumentAsync(new Document
{
Id = 2,
Properties = new List<Property>
{
new Property {Source = "Color", Value = "blue"},
new Property {Source = "Size", Value = "2"},
}
});
indexDocument = await client
.IndexDocumentAsync(new Document
{
Id = 3,
Properties = new List<Property>
{
new Property {Source = "Color", Value = "red"},
new Property {Source = "Size", Value = "1"},
}
});
var refreshAsync = client.Indices.RefreshAsync();
var query = new BoolQuery
{
Must = new QueryContainer[]
{
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Color"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] {"green", "blue"}
}
}
}
},
new NestedQuery
{
Path = "properties",
Query = new BoolQuery()
{
Must = new QueryContainer[]
{
new TermQuery()
{
Field = new Nest.Field("properties.source.keyword"),
Value = "Size"
},
new TermsQuery()
{
Field = new Nest.Field("properties.value.keyword"),
Terms = new[] {"2"}
}
}
}
}
}
};
var response = client.Search<Document>(s => s.Query(q => query));
foreach (var document in response.Documents)
{
Console.WriteLine($"Id: {document.Id}");
document.Properties.ForEach(Console.WriteLine);
Console.WriteLine();
}
}
}
打印:
Id: 1
Source: Color Value: green
Source: Size Value: 2
Id: 2
Source: Color Value: blue
Source: Size Value: 2
希望对您有所帮助。