全文搜索elasticsearch中的精确match_phrase(带有前导和尾随空格)

时间:2014-12-24 17:56:27

标签: elasticsearch lucene

我是Elasticsearch的新手,这是我的任务。

鉴于我的索引:

{
   "my_index": {
      "mappings": {
         "_default_": {
            "_all": {
               "enabled": false
            },
            "properties": {}
         },
         "title": {
            "_all": {
               "enabled": false
            },
            "properties": {
               "foo_id": {
                  "type": "long"
               },
               "title": {
                  "type": "string",
                  "analyzer": "english"
               }
            }
         }
      },
      "settings": {
         ...
      }
   }
}

样本记录:

{"foo_id": 777, "title": "Equality"}
{"foo_id": 777, "title": "First Among Equals"}
{"foo_id": 777, "title": "AN EQUAL MUSIC"}

我想搜索必须的记录:

  • 有foo_id == 777
  • 包含不区分大小写的单词“equal”

意思是,我必须只找到第三条记录,其中包含完全短语“相等”。不得退回包含“equality”和“equals”字样的标题。我想避免使用正则表达式。

我尝试了这样的搜索:

{
  "query": {
    "bool": {
      "must": [
        {"term": {"account_id": 777}},
        {"match_phrase": {"title": "equal"}}
      ]
    }
  }
}

但它会返回所有三个结果。

补充问题:如果我不关心结果的相关性,我怎样才能以最有效的方式获得结果?我应该使用search_type='scan'滚动还是过滤?一个片段会很好。感谢。

2 个答案:

答案 0 :(得分:2)

目前您正在使用english analyser

           "title": {
              "type": "string",
              "analyzer": "english"

如果您不想进行词干分析等(以避免选择“等于”,“相等”),请切换到更简单的分析器。例如,使用StandardSimple分析器 - 甚至创建自己的分析器。

           "title": {
              "type": "string",
              "analyzer": "standard"

设置完成后,使用matchquery_string查询查找相关文档。


如果您想保留Stem分析器但也支持其他形式的分析,那么您应该使用multi-fields

例如:

"title": {
    "type": "string",
    "analyzer": "english",
    "fields": {
       "std": { "type": "string", "analyzer": "standard" }
     }
}

如果您想使用standard分析器进行搜索,请使用字段title.std

答案 1 :(得分:1)

这是你可以做到的一种方式。如果您取出英语分析器,将使用standard analyzer代替,这似乎可以满足您的需求。

curl -XPUT "http://localhost:9200/my_index" -d'
{
    "settings": {
        "number_of_shards": 2, 
         "number_of_replicas": 1
      },
      "mappings": {
         "_default_": {
            "_all": {
               "enabled": false
            },
            "properties": {}
         },
         "title": {
            "_all": {
               "enabled": false
            },
            "properties": {
               "foo_id": {
                  "type": "long"
               },
               "title": {
                  "type": "string"
               }
            }
         }
      }
}'

然后添加文档:

curl -XPUT "http://localhost:9200/my_index/title/1" -d'
{"foo_id": 777, "title": "Equality"}'
curl -XPUT "http://localhost:9200/my_index/title/2" -d'
{"foo_id": 777, "title": "First Among Equals"}'
curl -XPUT "http://localhost:9200/my_index/title/3" -d'
{"foo_id": 777, "title": "AN EQUAL MUSIC"}'

然后,您可以使用constant score查询来避免额外的计算(如果您不关心结果的排名),并结合must bool filter来获得您想要的结果:< / p>

curl -XPOST "http://localhost:9200/my_index/_search" -d'
{
  "query": {
    "constant_score": {
       "filter": {
           "bool": {
               "must": [
                  {"term": {
                     "foo_id": 777
                  }},
                  {"term": {
                     "title": "equal"
                  }}
               ]
           }
       }
    }
  }
}'

得到以下特性:

{
   "took": 1,
   "timed_out": false,
   "_shards": {
      "total": 2,
      "successful": 2,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "my_index",
            "_type": "title",
            "_id": "3",
            "_score": 1,
            "_source": {
               "foo_id": 777,
               "title": "AN EQUAL MUSIC"
            }
         }
      ]
   }
}

以下是我使用的代码:

http://sense.qbox.io/gist/179d737edf1de964090746a2fdae5ad52c935b31

编辑:如果您希望能够使用英文分析仪以及标准分析仪(或其他分析仪,或者没有,通常是分面或分类的情况),您可以使用multi_field(不推荐使用的名称),如下所示:

curl -XPUT "http://localhost:9200/my_index" -d'
{
   "settings": {
      "number_of_shards": 2,
      "number_of_replicas": 1
   },
   "mappings": {
      "_default_": {
         "_all": {
            "enabled": false
         },
         "properties": {}
      },
      "title": {
         "_all": {
            "enabled": false
         },
         "properties": {
            "foo_id": {
               "type": "long"
            },
            "title": {
               "type": "string",
               "analyzer": "english",
               "fields": {
                  "unstemmed": {
                     "type": "string",
                     "analyzer": "standard"
                  }
               }
            }
         }
      }
   }
}'

现在,如果您使用{ "term": { "title": "equal" } }进行搜索,您将获得所有三个文档,但如果您使用{ "term": { "title.unstemmed": "equal" } },您将获得所需内容:

curl -XPOST "http://localhost:9200/my_index/_search" -d'
{
   "query": {
      "constant_score": {
         "filter": {
            "bool": {
               "must": [
                  {
                     "term": {
                        "foo_id": 777
                     }
                  },
                  {
                     "term": {
                        "title.unstemmed": "equal"
                     }
                  }
               ]
            }
         }
      }
   }
}'
...
{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 2,
      "successful": 2,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "my_index",
            "_type": "title",
            "_id": "3",
            "_score": 1,
            "_source": {
               "foo_id": 777,
               "title": "AN EQUAL MUSIC"
            }
         }
      ]
   }
}

以下是代码:

http://sense.qbox.io/gist/40a145e94fd8e47b875525c7e095024f025dd1ab