【问题标题】:Elasticsearch query to search from different fields non-strictlyElasticsearch 查询以非严格地从不同字段进行搜索
【发布时间】:2020-06-03 06:41:30
【问题描述】:

我对 elasticsearch 比较陌生,并且一直在 python 中使用 elasticsearch。我所拥有的是 csv 格式的人们数据,我已将其转换为 json 并添加到 elasticsearch 索引中。 字段如下:

'Last Name (Legal Name)', 
'First Name', 
'Middle Name', 
'Other Last Name', 
'Business Mailing Address City Name', 
'Business Mailing Address State Name',
'Business Practice Location Address City Name', 
'Business Practice Location Address State Name', 
'Authorized Official Last Name', 
'Authorized Official First Name', 
'Authorized Official Middle Name', 
'Authorized Official Title or Position'

我想在查询中输入类似“Name City”的内容。例如,“克林顿亚当斯汉密尔顿”,其中克林顿亚当斯是名字,汉密尔顿是城市。在大多数情况下,我不确定哪个是名字或哪个是最后一个,所以我需要从所有字段中进行匹配。

我现在使用的是这样的:

"query":{
                "query_string":{
                    "fields": ['Last Name (Legal Name)', 'First Name', 'Middle Name', 
                             'Other Last Name', 'Business Mailing Address City Name', 
                             'Business Mailing Address State Name',
                             'Business Practice Location Address City Name', 'Business Practice                            
                              Location Address State Name', 
                             'Authorized Official Last Name', 'Authorized Official First Name', 
                             'Authorized Official Middle Name', 
                             'Authorized Official Title or Position'],
                    "query": "(Clinton) AND (Adams) AND (Hamilton)",
                    }
                }

如果我从数据库中搜索确切的名称和城市,则以下查询可以正常工作,但如果名称中有拼写错误,或者某个名称中的名字缩写,则不会给出预期的结果。例如,如果查询类似于“Clinton A Hamilton”,它不会与任何文档匹配。我不能使用ORoperator,因为有多个名字相似的人,所以查询的所有部分——名字/姓氏和城市都很重要。我希望查询从索引中获取最相关的记录。

我尽力解释情况。无论如何,请随时询问是否有任何不清楚的地方。感谢您的建议。谢谢。

【问题讨论】:

  • 您好,我不知道您为什么要包含所有字段,而您想要考虑的只是人名和城市名称。
  • @glenacota 好吧,我明白城市和名称可以作为不同的查询进行查询,可能使用bool 运算符。您能建议在那之后继续前进的好方法吗?

标签: elasticsearch elastic-stack querydsl elasticsearch-dsl


【解决方案1】:

我要做的第一件事是优化您的文档映射。特别是,我会考虑保留这么多与名称相关的不同字段(例如,名字、姓氏、中间名、官方授权......)是否有意义,或者过滤一些并合并是否有意义别的东西。例如,此文档映射对您有意义吗?

{
  'name', 
  'business_mailing': {
    'city',
    'state'
  },
  'business_practice_location': {
    'city',
    'state'
  }
}

重点是,您应该根据要对其运行的查询来优化您的数据。

使用上面的映射,您可以运行包含两个match 查询的boolean querymust),可能配置the fuzzyness option 以解决拼写错误。例如,

{
  'query': {
    'bool': {
      'must': [{
        'match': {
          'name': { 'query': 'Clinton Adams', 'fuzzyness': 'AUTO'
        }
      },{
        'match': {
          'business_mailing': { 'query': 'Hamilton', 'fuzzyness': 'AUTO'
        }
      }]
    }
  }
}

另一种解决方案是使用copy_to 映射选项并定义一个新的可查询字段,其中包括名称字段和城市字段的值。这是文档的链接https://www.elastic.co/guide/en/elasticsearch/reference/7.5/copy-to.html

【讨论】:

  • 我更改了映射,并且我能够使用 bool 和 multi_match 获得所需的结果,因为现在我有两个全名字段(基本全名和授权一个)和两个位置字段(邮寄地址和商业实践地址)。我现在得到的结果不是_score 度量的递减顺序。您能否建议一种方法,以便我可以将最大分数文档作为输出?谢谢。
  • 你的意思是只得到一个结果,即得分最高的那个?在这种情况下,您可以将查询的“大小”设置为 1。(无论如何,如果您的问题得到回答,您会这样标记吗?:))
  • 是的,问题出现是因为我在 python 中使用了helper.scan 函数。如果我使用基本的es.search,我会得到所需的结果。非常感谢你的帮助。 :)
【解决方案2】:

首先,您应该尝试一下多重匹配查询,尤其是适合您用例的cross_field 类型。 Documentation here.

它将所有搜索的字段作为一个混合字段处理。

但是,如果您保留运算符“AND”,则对“Clinton A Hamilton”的查询将与“Clinton Adams / Hamilton”文档不匹配。 我认为您应该选择标准 OR 运算符。它会在第一个位置为您提供第一个相关文件。第一个完全匹配,之后是部分匹配。

如果您确定很多用户会使用小写形式作为名字,您应该考虑创建一个特殊的分析器来索引小写形式。

这是一个独立索引中的示例:

PUT diminutive
{
  "settings": {
    "analysis": {
      "filter": {
        "diminutive": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 3
        }
      }, 
      "analyzer": {
        "diminutive": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding",
            "diminutive"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "firstname": {
        "type": "text",
        "analyzer": "diminutive",
        "search_analyzer": "standard"
      }
    }
  }
}

然后您可以在'First Name' 的字段中使用小型分析器(请参阅文档here)并在多重匹配查询中添加子字段。

可能需要处理很多信息/概念,但我认为这对于您的用例来说应该是一个好的开始。

【讨论】:

  • 这是一个很好的方法,使用跨字段的 multi_match 会很有帮助。对我有用的是更改映射并连接不同的列。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 2023-03-26
  • 2023-01-17
  • 2017-07-12
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多