【问题标题】:Elasticsearch multiple filter conditions for nested array嵌套数组的Elasticsearch多重过滤条件
【发布时间】:2019-12-16 12:59:00
【问题描述】:

这个问题可能在某个地方得到了回答,但我找不到。所以我在寻求帮助 我的产品模型有一个嵌套的属性列表。像这样的

[
    {
        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 的产品。

我为我的搜索请求创建了这个查询,但它会返回一个空结果。

       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"}
                            }
                         }
                      }
                   }
                }
            }

你能帮我建立这种查询,我用错了什么吗? 谢谢你

【问题讨论】:

    标签: c# elasticsearch filter nested nest


    【解决方案1】:

    尝试用嵌套查询包装每个 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
    

    希望对您有所帮助。

    【讨论】:

    • 谢谢,这个解决方案看起来像我想要的那样工作。会给它一些测试运行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2017-07-27
    • 1970-01-01
    • 2015-12-13
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多