示例数据:
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 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确实并没有帮助我发现如何结合这两者。
最佳答案
是的,我必须使用分析仪...
添加任何数据之前,在创建索引时将分析器应用于这些字段。添加数据后,我找不到更简单的方法来执行此操作。
我发现的解决方案是将所有短语分解成每个单独的前缀,以便cross_fields
可以做到。您可以了解有关edge-ngram
here的使用的更多信息。
因此,现在不再搜索cross_field
短语,而不再搜索cats
短语,而是现在要搜索:c
,ca
,cat
和cats
以及后面的每个短语...因此text1
字段看起来像这样具有 flex :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
的相关性来实现的。
关于elasticsearch - 跨字段搜索,每个字段中有多个完整和不完整的短语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34777132/