簡體   English   中英

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的產品。

我為我的搜索請求創建了此查詢,但它將返回空結果。

       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

希望能有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM