【问题标题】:Elastic Search 2.0 search query in main object and nested object主对象和嵌套对象中的 Elastic Search 2.0 搜索查询
【发布时间】:2020-08-18 11:55:23
【问题描述】:

这是我的模型:

public class Student
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [Nested]
    public List<Subject> Subjects { get; set; }
}

public class Subject
{
    public int Id { get; set; }
    public string SubjectName { get; set; }        
}

映射:

mappings: {
  student: {
    properties: {
      firstName: {
        type: "string"
      },
      id: {
        type: "integer"
      },
      lastName: {
        type: "string"
      },
      subjects: {
        type: "nested",
        properties: {
          id: {
            type: "integer"
          },
          subjectName: {
            type: "string"
          }
       } 
    }
 }
}
}

要在嵌套对象(主题)中搜索,我使用以下代码,它会正确返回值。

var searchResponse = client.Search<Student>(s => s    
.Query(q => q
    .Nested(n => n
        .Path(p => p.VolunteerTasks)
        .Query(nq => nq.Match(m => m
            .Query(searchText).Field("subjects.subjectName"))))));
 return searchResponse.Documents;

但我想使用相同的 searchText 搜索 student.firstNamestudent.lastNamesubjects.subjectName。 我该怎么做?

【问题讨论】:

  • 运气好吗?如果您需要更多信息,请发表评论
  • 是的,下面的答案可以帮助我找到解决方案。但现在我有另一个问题。我需要为 searchText 输入确切的单词才能得到结果。例如 SubjectName - "Science and technology" 如果我​​用技术搜索,它会返回记录。但是如果用techno搜索,它没有返回记录。我该如何解决这个问题?
  • 为您评论中提到的要求提供了答案,理想情况下它是一个新要求,根据社区指南,您应该问一个不同的问题,所以建议再问一个问题,然后将我的答案转移到您的新问题也是如此。另外,由于我对原始问题的上一个回答很有帮助,因此如果您也对此表示赞同,那就太好了。提前致谢
  • 感谢 Opster Elasticsearch Ninja。 jaspreet chahal 给出的答案帮助我解决了我的问题。我已经为此stackoverflow.com/questions/61629848/… 提出了一个单独的问题,你能检查一下并帮助我解决我的问题吗?谢谢
  • 我以rest API的形式给出了方法和答案,它解决了这个问题。至少你可以投票,因为这些对寻找方法的人仍然有用

标签: c# elasticsearch nested elasticsearch-query elasticsearch-2.0


【解决方案1】:

以 REST API 的形式提供答案,您可以将其转换为 c# 格式,因为我不熟悉它的语法,这对不寻找特定语言答案的人会有所帮助。

使用您的示例数据对此进行了测试,以下是可行的解决方案

索引定义

{
    "student": {
        "properties": {
            "firstName": {
                "type": "string"
            },
            "id": {
                "type": "integer"
            },
            "lastName": {
                "type": "string"
            },
            "subjects": {
                "type": "nested",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "subjectName": {
                        "type": "string"
                    }
                }
            }
        }
    }
}

**没有opstersubjectfirstname 的索引示例文档**

{
    "firstName": "Isuru",
    "lastName": "foo",
    "id": 1,
    "subjects": [
        {
            "id": 100,
            "subjectName": "math"
        },
        {
            "id": 101,
            "subjectName": "opster"
        }
    ]
}

索引另一个在任何主题名称中都没有 opster 的文档

{
    "firstName": "opster",
    "lastName": "tel aviv",
    "id": 1,
    "subjects": [
        {
            "id": 100,
            "subjectName": "math"
        },
        {
            "id": 101,
            "subjectName": "science"
        }
    ]
}

搜索查询,请根据您的要求将must改为should

{
    "query": {
        "bool": {
            "should": [    --> note
                {
                    "match": {
                        "firstName": "opster"
                    }
                },
                {
                    "nested": {
                        "path": "subjects",
                        "query": {
                            "bool": {
                                "must": [   -->note
                                    {
                                        "match": {
                                            "subjects.subjectName": "opster"
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}

搜索结果

"hits": [
            {
                "_index": "nested",
                "_type": "student",
                "_id": "1",
                "_score": 0.39103588,
                "_source": {
                    "firstName": "opster",
                    "lastName": "tel aviv",
                    "id": 1,
                    "subjects": [
                        {
                            "id": 100,
                            "subjectName": "math"
                        },
                        {
                            "id": 101,
                            "subjectName": "science"
                        }
                    ]
                }
            },
            {
                "_index": "nested",
                "_type": "student",
                "_id": "2",
                "_score": 0.39103588,
                "_source": {
                    "firstName": "Isuru",
                    "lastName": "foo",
                    "id": 1,
                    "subjects": [
                        {
                            "id": 100,
                            "subjectName": "math"
                        },
                        {
                            "id": 101,
                            "subjectName": "opster"
                        }
                    ]
                }
            }
        ]

【讨论】:

    【解决方案2】:

    您需要添加一个 should 子句,其中包含对名字和姓氏的匹配查询 以及对主题名称的嵌套查询。您不能在单个匹配或多匹配查询中包含嵌套和非嵌套查询

    var searchResponse = _elasticClient.Search<AssociateProfile>(s => s
                         .Query(q => q
                                     .Bool(b=>b
                                                 .Should(
                                                            sh => sh.Match(m => m.Query(searchText).Field("student.firstName")),
                                                            sh => sh.Match(m => m.Query(searchText).Field("student.lastName")),
                                                             sh => sh.Nested(n => n
                                                                                   .Path(p => p.VolunteerTasks)                                                                                           .Query(nq => nq.Match(m => m                                                                                           .Query(searchText).Field("subjects.subjectName")))
                                                                                        )
    
                                                                       )
                                                        )
                                                  ));
    

    【讨论】:

      【解决方案3】:

      根据 OP 的评论,添加提供部分匹配的答案。比如如果文档包含Science and technology 并且搜索techno 也应该来。 请注意使用自定义 edge-n-gram 分析器来实现此要求。

      索引定义

      {
        "settings": {
          "analysis": {
            "filter": {
              "autocomplete_filter": {
                "type": "edge_ngram",
                "min_gram": 1,
                "max_gram": 10
              }
            },
            "analyzer": {
              "autocomplete": { 
                "type": "custom",
                "tokenizer": "standard",
                "filter": [
                  "lowercase",
                  "autocomplete_filter"
                ]
              }
            }
          }
        },
        "mappings": {
          "properties": {
            "title": {
              "type": "text",
              "analyzer": "autocomplete", 
              "search_analyzer": "standard" 
            }
          }
        }
      }
      

      索引示例文档

      {
          "title" : "Science and technology"
      }
      

      搜索查询

      {
          "query" :{
              "match" :{
                  "title" :"techno"
              }
          }
      }
      

      搜索结果

       "hits": [
                  {
                      "_index": "edge",
                      "_type": "_doc",
                      "_id": "1",
                      "_score": 0.44104567,
                      "_source": {
                          "title": "Science and technology"
                      }
                  }
              ]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-28
        • 2021-08-12
        相关资源
        最近更新 更多