这里有一些建议,即使我有一些疑问,我也理解您的要求是正确的。
基本思想是操纵您放入索引(位置)中的内容,因为您想要匹配比您实际存储在文档中的内容更大的内容。另外,我想强调的是,我认为这不会是一个黑白分明的情况,您要么得到一个(正确的)答案,要么根本没有答案。比赛总会有一个“分数”。
另一点是,您需要知道如何操作您的位置,这样,根据您预测人们将使用的查询,这些操作将在大多数情况下(并非所有情况)对您有所帮助。更好的说法是,索引位置和您对它们执行的操作的组合将使您有更高的机会匹配大多数查询。
以下是一些具体的想法:
使用带状疱疹。我相信这是您拥有有序术语概念的唯一选择。你说你有一个自由形式的查询。这意味着在您的查询中,您只想将该查询放在其他地方,不被划分为术语,不删除停用词或类似的东西。这意味着您不能使用可以给您命令的span_near 。
使用带状疱疹,您还可以摆脱用户输入“ca francisco san”的情况。
第一个位置操作的想法:存储完整的位置名称,以及(除了上面的带状疱疹)。对于那些实际上完全匹配您的位置文档的查询,这将为您提供更高的分数。而且,由于我从您的示例中看到您有多个位置组合,因此您的“位置”索引的“质量”很有可能为您提供良好的匹配结果。
"settings": {
"analysis": {
"filter": {
"my_shingle_filter": {
"type": "shingle",
"min_shingle_size": 2,
"max_shingle_size": 2,
"output_unigrams": true // this is true for situations where you have "paris france" in locations but user searches for "paris"
}
},
"analyzer": {
"my_shingle_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"my_shingle_filter"
]
}
}
}
},
"mappings": {
"locations": {
"properties": {
"name": {
"type": "string",
"analyzer": "my_shingle_analyzer",
"fields": {
"full": {
"type": "string",
"analyzer": "keyword"
}
}}}}}
使用映射转换来提高位置索引的质量。name.full
意思是,我上面提到的那些操作 - 他们将根据与查询术语相关的预测向您的索引添加额外的字段(就像上面一样)。
第一个示例来自您的一个查询示例:“旧金山的纽约风格披萨”。对于索引中的每个位置,添加另一个应具有in
前缀的字段:in san francisco
等in new york
。
"transform": [
{
"script": "full_plus_in = 'in ' + ctx._source['name']; ctx._source['name.full_plus_in'] = full_plus_in",
"lang": "groovy"
}
...
第二个示例是通过向places
映射中的新字段添加后缀。假设在您的预测中可以认为“旧金山的新式披萨店”之类的查询很常见:
{"script": "full_plus_places = ctx._source['name'] + ' places'; ctx._source['name.full_plus_places'] = full_plus_places",
"lang": "groovy"}
把它们放在一起是一个初步的映射:
{
"settings": {
"analysis": {
"filter": {
"my_shingle_filter": {
"type": "shingle",
"min_shingle_size": 2,
"max_shingle_size": 2,
"output_unigrams": true
}
},
"analyzer": {
"my_shingle_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"my_shingle_filter"
]
}
}
}
},
"mappings": {
"locations": {
"transform": [
{
"script": "full_plus_in = 'in ' + ctx._source['name']; ctx._source['name.full_plus_in'] = full_plus_in",
"lang": "groovy"
},
{"script": "full_plus_places = ctx._source['name'] + ' places'; ctx._source['name.full_plus_places'] = full_plus_places",
"lang": "groovy"}
],
"properties": {
"name": {
"type": "string",
"analyzer": "my_shingle_analyzer",
"fields": {
"full": {
"type": "string",
"analyzer": "keyword"
},
"full_plus_in": {
"type": "string",
"analyzer": "keyword"
},
"full_plus_places": {
"type": "string",
"analyzer": "keyword"
}
}
}
}
}
}
}
测试数据:
{"index":{}}
{"name":"denver co"}
{"index":{}}
{"name":"miami fl"}
{"index":{}}
{"name":"new york city ny"}
{"index":{}}
{"name":"san francisco ca"}
{"index":{}}
{"name":"paris france"}
{"index":{}}
{"name":"bay area ca"}
{"index":{}}
{"name":"dallas texas"}
{"index":{}}
{"name":"san francisco california"}
{"index":{}}
{"name":"new york city new york"}
示例查询:
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "i want san francisco ca places having new york style pizza"
}
}
],
"should": [
{"match": {
"name.full": "i want san francisco ca places having new york style pizza"
}},
{"match": {
"name.full_plus_in": "i want san francisco ca places having new york style pizza"
}},
{"match": {
"name.full_plus_places": "i san francisco ca places having new york style pizza"
}}
]
}
}
}
第一个匹配的位置应该是最好的(考虑到它得到的分数)。