首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在给定查询中搜索索引短语

如何在给定查询中搜索索引短语
EN

Stack Overflow用户
提问于 2014-11-04 16:50:56
回答 1查看 623关注 0票数 2

给定来自用户的自由格式查询,我试图确定它是否包含位置短语。

示例:给定自由格式的查询"san francisco ca中的纽约风格比萨饼“,并给出包含”丹佛公司“、”迈阿密fl“、”纽约纽约“、”旧金山ca“、”巴黎法国“等位置短语的文档索引,则匹配的文档将包含位置短语"san francisco ca”。

包含位置短语的索引还包含允许的排列,在单独的文档中。在上面的例子中,我可能有"san francisco ca“、"san francisco california",还有可能还有"sf”、"bay area ca“等其他文件,这些文档都是索引中的单独文档。大写和标点符号将被预先丢弃,所以查询“纽约风格的披萨,在旧金山,在加州”将变成“纽约风格的披萨在旧金山,在加州”。

我还应该提到,如果有一种更好或需要的方法来为特定类型的查询索引位置,例如在不同的领域中有"city“和"state”和"country“,我也可以这样做,而且我非常愿意听取建议。

到目前为止我尝试过的是:

  1. 普通的老匹配查询。似乎效果最好,但忽略了命令.“旧金山ca”是匹配的,而"ca francisco san“不应该匹配。也忽略了位置。
  2. 短语匹配。根本不起作用,因为由于输入查询中的额外条款(“纽约式比萨饼”),我没有得到匹配。
  3. 多字段匹配,cross_fields选项。与匹配查询相同的问题;忽略排序和位置。这是用索引的一个版本尝试的,其中"city“和"state”等是不同的字段。
  4. 渗出。根本无法工作。调用GET ./_percolate检索索引中的所有文档。此外,构建.percolator类型非常缓慢,最终使我的实例(JVM内存99%)崩溃,而使用的是大容量api。我的数据库中有大约100万个位置,我认为这对percolator来说太大了,percolator一直在120 K左右崩溃。据我所读,我不认为这是一个合适的用例,但不确定。

我没试过的原因是:

  1. 带状疱疹。给定位置的术语数量是可变的(即“达拉斯德克萨斯州”对“旧金山加州”和“纽约市纽约”),而瓦牌似乎适用于特定数量的术语。
  2. query_string。我不想要求用户把短语放在双引号中。我也不想要查询语言(OR,AND,等等)。同时,忽略位置。

我花了3-4天来解决这个问题,希望能得到一些温和的指导。示例查询/索引/映射将是很棒的,但是即使让我知道我应该使用的查询类型(以及索引和映射),也会非常有用,所以我至少可以“把正确的树树皮化”!

我愿意将其他工具与ES结合使用,只要它们是开源的、可免费获得的、支持和使用得相当好的。位置数据库包含~1M记录。

奖励:我假设位置短语(如果有的话)将接近查询的末尾。以某种方式感觉到这一点或相应地促进结果将是很好的。注意,我不想将此作为绝对要求;如果用户提交查询“我希望旧金山ca比萨饼场所拥有纽约风格的比萨饼”,给定前面描述的索引的唯一有效位置短语是"san francisco ca“,这应该是匹配的。

奖金2X:我有每个地点的人口信息。为更高的人口稍微提高结果的一些方法也是很棒的(我已经尝试了function_score与field_value_factor函数和ln1p修饰符,它看起来很好,但不确定如果我最终使用percolator,它将如何工作)。

奖励3X!:容纳轻微的排字,例如“旧金山”将是很好的。

我使用的是ElasticSearch 1.3.2。

谢谢!!

编辑:为了清楚起见,我正在寻找短语搜索,当索引短语比查询短时,正如这里很好地描述的,但不幸的是没有完全解决:

Solr:当索引短语比查询短时,短语搜索

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-07 10:03:38

这里有一些建议,即使我有一些怀疑,我理解你的要求是正确的。

基本思想是操作您在索引(位置)中放置的内容,因为您希望匹配比实际存储在文档中的内容更大的内容。此外,我想强调的是,我不认为这将是一个黑白的情况下,你要么得到一个(正确的)答案或根本没有答案。比赛总会有“分数”。

另一点是,您需要知道如何操作您的位置,这样,考虑到您预测的用户将使用什么查询,这些操作将帮助您处理大多数案例(而不是all cases)。更好地说,索引位置和您对它们执行的操作的组合将给您更高的匹配大多数查询的机会。

以下是一些具体的想法:

  1. 用瓦。我认为这是唯一的选项,您可以使用有序项的概念。你说你有一个自由形式的查询。这意味着在您的查询中,您只想将该查询放入其他任何内容,不被划分为术语,不删除停止词或诸如此类的内容。这意味着您不能使用近处,因为它可以给您订单。 使用shingles,您还可以消除用户输入"ca francisco san“的情况。
  2. 第一个位置操作的想法:存储完整的位置名称,以及(除了上面的瓦)。这将为那些与您的位置文档完全匹配的查询提供更高的分数。而且,由于我已经从您的例子中看到您有多个位置组合,所以很有可能您的“位置”索引的“质量”会给您提供良好的匹配结果。
代码语言:javascript
复制
  "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"
            }
   }}}}}
  1. 使用映射变换来提高您的位置索引的质量。也就是说,我前面提到的那些操作--它们将根据与查询术语相关的预测向索引中添加额外的字段(就像上面的name.full )。 第一个示例来自您的一个查询示例:“位于旧金山的纽约风格比萨饼”。对于索引中的每个位置,添加另一个应该具有in前缀的字段:in san franciscoin new york等。
代码语言:javascript
复制
"transform": [
        {
        "script": "full_plus_in = 'in ' + ctx._source['name']; ctx._source['name.full_plus_in'] = full_plus_in",
        "lang": "groovy"
        }
...

第二个例子是将places后缀添加到映射中的一个新字段。假设在您的预测中,像“旧金山新风格比萨饼的位置”这样的查询可以被认为是频繁的:

代码语言:javascript
复制
{"script": "full_plus_places = ctx._source['name'] + ' places'; ctx._source['name.full_plus_places'] = full_plus_places",
        "lang": "groovy"}

把所有这些放在一起是一个初步的映射:

代码语言:javascript
复制
{
  "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"
            }
          }
        }
      }
    }
  }
}

测试数据:

代码语言:javascript
复制
{"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"}

示例查询:

代码语言:javascript
复制
{
  "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"
        }}
      ]
    }
  }
}

第一个匹配位置应该是最好的(考虑到它得到的分数)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26740620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档