【问题标题】:Cross Field Search with Multiple Complete and Incomplete Phrases in Each Field每个字段中包含多个完整和不完整短语的跨字段搜索
【发布时间】:2016-01-13 21:14:52
【问题描述】:

示例数据:

PUT /test/test/1
{
    "text1":"cats meow",
    "text2":"12345",
    "text3":"toy"
}

PUT /test/test/2
{
    "text1":"dog bark",
    "text2":"98765",
    "text3":"toy"
}

还有一个示例查询:

GET /test/test/_search
{
    "size": 25,
    "query": {
        "multi_match" : {
            "fields" : [
                "text1", 
                "text2",
                "text3"
            ],
            "query" : "meow cats toy",
            "type" : "cross_fields"
        }
    }
}

返回 cat 先命中,然后是 dog,这就是我想要的。

但是当您查询cat toy 时,猫和狗的相关性得分相同。我希望能够考虑该单词的前缀(可能还有该字段中的其他几个单词),然后运行cross_fields

所以如果我搜索:

GET /test/test/_search
{
    "size": 25,
    "query": {
        "multi_match" : {
            "fields" : [
                "text1", 
                "text2",
                "text3"
            ],
            "query" : "cat toy",
            "type" : "phrase_prefix"
        }
    }
}

GET /test/test/_search
{
    "size": 25,
    "query": {
        "multi_match" : {
            "fields" : [
                "text1", 
                "text2",
                "text3"
            ],
            "query" : "meow cats",
            "type" : "phrase_prefix"
        }
    }
}

我应该得到 cat/ID 1,但我没有。

我发现使用cross_fields 可以实现多词短语,而不是多不完整短语。而phrase_prefix 实现了不完整的词组,而不是多个不完整的词组...

筛选documentation 确实无助于我发现如何将这两者结合起来。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    是的,我必须使用分析仪......

    在添加任何数据之前创建索引时,分析器会应用于字段。添加数据后,我找不到更简单的方法来执行此操作。

    我找到的解决方案是将所有短语分解为每个单独的前缀,这样cross_fields 就可以做到这一点。可以详细了解edge-ngramhere的使用。

    所以不是cross_field 只是搜索cats 短语,而是搜索:ccacatcats 以及之后的每个短语......所以@987654331 @ 字段看起来像这样弹性:c ca cat cats m me meo meow.

    ~~~

    以下是使上述问题示例起作用的步骤:

    首先创建并命名分析器。要了解更多过滤器值的含义,我建议您查看this

    PUT /test
    {
        "settings": {
            "number_of_shards": 1, 
            "analysis": {
                "filter": {
                    "autocomplete_filter": { 
                        "type":     "edge_ngram",
                        "min_gram": 1,
                        "max_gram": 20
                    }
                },
                "analyzer": {
                    "autocomplete": {
                        "type":      "custom",
                        "tokenizer": "standard",
                        "filter": [
                            "lowercase",
                            "autocomplete_filter" 
                        ]
                    }
                }
            }
        }
    }
    

    然后我将此分析器附加到每个字段。 我更改了 text1 以匹配我应用它的字段。

    PUT /test/_mapping/test
    {
        "test": {
            "properties": {
                "text1": {
                    "type":     "string",
                    "analyzer": "autocomplete"
                }
            }
        }
    }
    

    我运行GET /test/_mapping 以确保一切正常。

    然后添加数据:

    POST /test/test/_bulk
    { "index": { "_id": 1 }}
    { "text1": "cats meow", "text2": "12345", "text3": "toy" }
    { "index": { "_id": 2 }}
    { "text1": "dog bark", "text2": "98765", "text3": "toy" }
    

    还有搜索!

    {
        "size": 25,
        "query": {
            "multi_match" : {
                "fields" : [
                    "text1", 
                    "text2",
                    "text3"
                ],
                "query" : "cat toy",
                "type" : "cross_fields"
            }
        }
    }
    

    返回:

    {
       "took": 3,
       "timed_out": false,
       "_shards": {
          "total": 1,
          "successful": 1,
          "failed": 0
       },
       "hits": {
          "total": 2,
          "max_score": 0.70778143,
          "hits": [
             {
                "_index": "test",
                "_type": "test",
                "_id": "1",
                "_score": 0.70778143,
                "_source": {
                   "text1": "cats meow",
                   "text2": "12345",
                   "text3": "toy"
                }
             },
             {
                "_index": "test",
                "_type": "test",
                "_id": "2",
                "_score": 0.1278426,
                "_source": {
                   "text1": "dog bark",
                   "text2": "98765",
                   "text3": "toy"
                }
             }
          ]
       }
    }
    

    当您搜索cat toy 时,这会在两者之间形成对比,而之前的分数是相同的。但现在,cat 命中的得分更高,这是理所当然的。这是通过考虑每个短语的每个前缀(在这种情况下/短语中最多 20 个字符),然后查看数据与 cross_fields 的相关性来实现的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-22
      • 2018-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 2012-11-12
      相关资源
      最近更新 更多