簡體   English   中英

如何使用 C# NEST 在 ElasticSearch 中搜索數組的動態元素?

[英]How to search dynamic elements of array in ElasticSearch using C# NEST?

我的 elasticsearch 中有這些數據,具有這種結構。

在此處輸入圖像描述

如何從這個數組中搜索 firstName、middleName 和 surname? 注意: NameDetails數組長度是動態的。 Person A 可能只有一個NameDetails元素。 人 B 可以有 3 個NameDetails元素。

目前,我只能按gender搜索。 我正在使用 NEST nuget C#。 這是我的查詢。

var response = await _elasticClient.SearchAsync<Person>(s => s
          .Query(q => q
              .Bool(b => b.Must(
                mu => mu
                .Match(m => m
                 .Field(f => f.Gender)
                 .Query(Gender)
                )

                )
              )
          )
        );

在此處輸入圖像描述

在 NEST 中,我嘗試使用此代碼但未返回任何結果。

        var response = _elasticClient.Search <Model.Entities.Split.Person.Person> (s => s
            .Index("person")
            .Query(q => q
                .Match(m => m
                    .Field(f => f.NameDetails.Name[0].NameValue.FirstName)
                    .Query("Fawsu")
                )
            )
        );

但是,如果我直接在 ElasticSearch 上運行 DSL 查詢並使用下面的查詢,它會返回結果。

GET /person/_search
{
  "query": {
    "match": {
          "nameDetails.nameValue.firstName": {
            "query": "Fawsu"
          }
        }
    }
  }
}

或者

GET /person/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "fuzzy": {
            "nameDetails.nameValue.surname": {
              "value": "Pibba",
              "fuzziness": "AUTO"
            }
          }
        },
        
        {
          "fuzzy": {
            "nameDetails.nameValue.firstName": {
              "value": "Fawsu",
              "fuzziness": "AUTO"
            }
          }
        }
      ]
    }
  }
}

看看它是如何映射到 POCO 的很有用

public class Person
{
    public string Gender { get; set; }
    public string ActiveStatus { get; set; }
    public string Deceased { get; set; }
    public List<Name> NameDetails { get; set; }
}

public class Name
{
    public List<NameValue> NameValue { get; set; }
    public string NameType { get; set; }
}

public class NameValue
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
}

(您可能會將其中一些字段作為字符串以外的類型使用 map,我將把它作為練習留給讀者)。

搜索名字

var client = new ElasticClient();


var response = client.Search<Person>(s => s
    .Index("people")
    .Query(q => q
        .Match(m => m
            .Field(f => f.NameDetails[0].NameValue[0].FirstName)
            .Query("Fawsu")
        )
    )
);

產生查詢

POST http://localhost:9200/people/_search?pretty=true&typed_keys=true 
{
  "query": {
    "match": {
      "nameDetails.nameValue.firstName": {
        "query": "Fawsu"
      }
    }
  }
}

.Field(f => f...)中的表達式是構建"nameDetails.nameValue.firstName"路徑的表達式,它將在名稱值和名稱詳細信息的任何名字中查找匹配項。 它使用索引器的事實並不意味着它針對名字詳細信息的名字值,而只是一種遍歷 object 圖來構建表達式的方法。

要構建一個復合查詢來定位相同名稱值的多個值, NameNameValue都需要映射為nested數據類型,然后使用嵌套查詢。

對於單個字段

var response = client.Search<Person>(s => s
    .Index("people")
    .Query(q => q
        .Nested(n => n
            .Path(f => f.NameDetails)
            .Query(nq => nq
                .Nested(nn => nn
                    .Path(f => f.NameDetails[0].NameValue)
                    .Query(nnq => nnq
                        .Match(m => m
                            .Field(f => f.NameDetails[0].NameValue[0].FirstName)
                            .Query("Fawsu")
                        )
                    )
                )
            )
        )
    )
);

對於多個字段

var response = client.Search<Person>(s => s
    .Index("people")
    .Query(q => q
        .Nested(n => n
            .Path(f => f.NameDetails)
            .Query(nq => nq
                .Nested(nn => nn
                    .Path(f => f.NameDetails[0].NameValue)
                    .Query(nnq => nnq
                        .Bool(b => b
                            .Must(m => m
                                .Match(m => m
                                    .Field(f => f.NameDetails[0].NameValue[0].FirstName)
                                    .Query("Fawsu")
                                ), m => m
                                .Match(m => m
                                    .Field(f => f.NameDetails[0].NameValue[0].LastName)
                                    .Query("Pibba")
                                )
                            )
                        )
                    )
                )
            )
        )
    )
);

后者導致查詢

POST http://localhost:9200/people/_search?pretty=true&typed_keys=true 
{
  "query": {
    "nested": {
      "path": "nameDetails",
      "query": {
        "nested": {
          "path": "nameDetails.nameValue",
          "query": {
            "bool": {
              "must": [
                {
                  "match": {
                    "nameDetails.nameValue.firstName": {
                      "query": "Fawsu"
                    }
                  }
                },
                {
                  "match": {
                    "nameDetails.nameValue.lastName": {
                      "query": "Pibba"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

如果您想搜索以下內容:

firstName == "John" AND middleName == "Ben" AND lastName == "smith"

然后您可以使用TermQuery搜索firstNamemiddleNamelastName

我更熟悉Object 初始化語法(需要using static Nest.Infer

using static Nest.Infer;

var query = new TermQuery
{
    Name = "my firstName query",
    Field = Field<Person>(p => p.firstName),
    Value = "John"
};

您將需要為middleNamelastName再編寫 2 個查詢,然后對所有這些查詢進行AND


如果您想搜索以下內容:

firstName == "John" OR middleName == "John" OR lastName == "John"

然后你可以使用Multi-match Query

using static Nest.Infer;

var query = new MultiMatchQuery
{
    Name = "My Multi-match query",
    Fields = Field<Person>(p => p.firstName, 1.1) // 1.1 is boost (default is 1)
        .And<AdDocument>(p => p.middleName, 1)
        .And<AdDocument>(p => p.lastName, 1)
    Query = "John"
    //Fuzziness = Fuzziness.Auto
};

暫無
暫無

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

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