弹性搜索 - 具有数组类型和嵌套对象属性的复杂查询

Joh*_*n K 2 indexing elasticsearch

鉴于以下映射,我需要获得符合以下条件的结果

  1. 名字,姓氏,date_of_birth和Active = true OR完全匹配
  2. 名字,姓氏,Active = true和1封电子邮件中的完全匹配可能的倍数OR
  3. 第一个名字,姓氏,Active = true和1个traveldocument 数字与可能的倍数完全匹配

电子邮件和旅行证件可以指一系列物品.

    {
    "profile":{
        "properties":{

            "date_of_birth":{
                "type":"date",
                "store":"no"
            },
            "first_name":{
                "type":"string",
                "store":"no"
            },
            "last_name":{
                "type":"string",
                "store":"no"
            },
            "email":{
                "type":"string",
                "store":"no"
            },
            "active":{
                "type":"string",
                "store":"no"
            },
            "travel_document":{
              "properties" : {
                   "countryOfCitizenship" : {"type" : "string"},
                   "countryOfIssue" : {"type" : "string"},
                   "expirationDate" : {"type" : "date"},
                   "nationality" : {"type" : "string"},
                   "number" : {"type" : "string"},
                   "addressLines" : {"type": "string"},
                   "issuedForAreaCode" : {"type": "string"},
                   "type" : {"type": "string"}
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在elasticsearch中执行这种搜索?我可以使用嵌套查询执行此操作吗?

DrT*_*ech 7

是的你可以.

首先,回答有关嵌套查询的问题:

如果需要在对象集合中查询SAME OBJECT中的多个字段(例如travel_document.nationality,travel_document.expirationDate然后您需要travel_document从类型更改object为类型nested并使用嵌套查询.

在您给出的示例查询中,您尚未显示需要此功能.相反,你问的是否有任何travel_document价值.因此,在这种情况下,您不需要使用嵌套功能.

(如果您认为将来可能需要对相关字段进行查询,那么您可能确实想要使用nested.您还可以include_in_root将嵌套对象设置为单独的nested对象和主文档中的索引).

对于下面的查询,我假设它travel_document不是嵌套的.

第二:您在名称字段中使用"完全匹配".

默认情况下,会分析字符串字段,因此"Mary Jane"将被编入索引['mary','jane'].如果您在该字段上运行查询以查找"Mary",那么它将匹配,因为该字段确实包含"mary".但是,这不完全匹配.

如果你想进行精确匹配,那么你需要创建字段not_analyzed,在这种情况下,"Mary Jane"将被索引为单个术语"Mary Jane",并且"Mary"的查询将不匹配.缺点是在这种情况下您无法在名称字段上使用全文查询.

类似地,将电子邮件字段not_analyzed(或使用带有keywordtokenizer 的自定义分析器- 不对字符串进行标记化 - 以及lowercase令牌过滤器)可能更有意义.

在下面的查询中,我假设您的名称字段已分析,并且您的电子邮件字段未分析:

curl -XGET 'http://127.0.0.1:9200/my_index/properties/_search?pretty=1'  -d '
{
   "query" : {
      "filtered" : {
         "query" : {
            "bool" : {
               "must" : [
                  {
                     "match_phrase" : {
                        "first_name" : "mary jane"
                     }
                  },
                  {
                     "match_phrase" : {
                        "last_name" : "smith"
                     }
                  }
               ]
            }
         },
         "filter" : {
            "and" : [
               {
                  "term" : {
                     "active" : 1
                  }
               },
               {
                  "or" : [
                     {
                        "term" : {
                           "date_of_birth" : "1980-01-01"
                        }
                     },
                     {
                        "terms" : {
                           "email" : [
                              "mary@smith.com",
                              "maryjane@smith.com"
                           ]
                        }
                     },
                     {
                        "terms" : {
                           "travel_document.number" : [
                              "1234",
                              1235
                           ]
                        }
                     }
                  ]
               }
            ]
         }
      }
   }
}
'
Run Code Online (Sandbox Code Playgroud)