弹性搜索允许用户选择使用完全匹配

时间:2015-04-13 20:48:49

标签: elasticsearch

我在弹性搜索中使用了multi_match查询,因为我只对3个字段感兴趣。

    query: {
      filtered: {
        query: {
          multi_match: {
            fields: ['subject', 'text', 'task_comments.text'],
            query: USER_INPUT
          }
        }
      }
    }

如果我搜索Apple TV,我会收到“Apple TV”,Apple和TV的结果。

我希望用户根据他们的输入选择搜索完全匹配。因此,如果他们搜索“Apple TV”(带双引号),它应该只返回包含“Apple TV”的结果。不应返回仅包含Apple的结果。

是否可以仅使用弹性搜索执行此操作?

或者我是否需要根据用户的输入更改应用程序生成的查询?

1 个答案:

答案 0 :(得分:1)

您可以将索引设置为也包含" raw"对于您要搜索的每个字段,未分析sub-field

作为一个玩具示例,我设置了一个简单的索引,并添加了一些文档:

PUT /test_index
{
    "mappings": {
        "doc":{
            "properties": {
                "text_field": {
                    "type": "string",
                    "analyzer": "standard",
                    "fields": {
                        "raw": {
                            "type": "string", 
                            "index": "not_analyzed"
                        }
                    }
                }
            }
        }
    }
}

POST /test_index/doc/_bulk
{"index":{"_id":1}}
{"text_field": "Apple TV"}
{"index":{"_id":2}}
{"text_field": "Apple iPhone"}
{"index":{"_id":3}}
{"text_field": "Apple MacBook"}

此索引使用standard analyzer作为主要字段(指定它是多余的,因为它是默认值,但我想明确它),并且根本没有分析器用于子字段。

因此,如果我搜索主要字段,我会收到所有三个文档:

POST /test_index/_search
{
    "query": {
        "match": {
           "text_field": "Apple TV"
        }
    }
}
...
{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 3,
      "max_score": 0.98479235,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 0.98479235,
            "_source": {
               "text_field": "Apple TV"
            }
         },
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "2",
            "_score": 0.10063131,
            "_source": {
               "text_field": "Apple iPhone"
            }
         },
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "3",
            "_score": 0.10063131,
            "_source": {
               "text_field": "Apple MacBook"
            }
         }
      ]
   }
}

但如果我搜索" raw"子领域,我只回到一个文档:

POST /test_index/_search
{
    "query": {
        "match": {
           "text_field.raw": "Apple TV"
        }
    }
}
...
{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1.4054651,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 1.4054651,
            "_source": {
               "text_field": "Apple TV"
            }
         }
      ]
   }
}

您应该可以为每个字段执行此操作,以使其与multi_match查询一起使用。或者,您可以使用_all field进行设置,然后只对其使用"match"查询。

以下是一个地方的代码:

http://sense.qbox.io/gist/31ff17997b4971b6515f019ab514f9a17da1a606