如何在elasticsearch中执行快速精确匹配搜索

时间:2013-11-12 22:48:40

标签: elasticsearch

假设我在用户/数据中有一个用户对象:

{"_id": 123, "name": "Bob"}

并且用户有多个宠物,其宠物文档如下所示:

{"_id": 1423, "owner": 123, "type": "cat", "name": "Prince McNugget"}
{"_id": 1830, "owner": 123, "type": "dog", "name": "Tarley"}

在弹性搜索中执行快速(即索引)搜索以找到所有者123的所有宠物文档的正确方法(或有哪些好选项)?

我已经阅读了“完全匹配”问题的答案,该问题建议使用字段“not_analyzed”的映射,但我会假设“not_analyzed”字段未编入索引,因此数据库必须执行类似于全表扫描的东西(我在这里与SQL比较)才能得出结果。这对我来说是不可接受的 - 我需要它作为索引搜索。

3 个答案:

答案 0 :(得分:2)

您可以在宠物身上使用term queryhttp://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-query.html

{
  "query": {
    "term" : { "owner" : 123 }
  }
}

在ES中,除非您配置不对其进行索引,否则所有内容都会被编入索引,因此默认情况下它应该很快。

编辑:“not_analyzed”就像mcollin解释的那样。它告诉ES不要分析数据(将数据保存为我们传递的内容),除非您指定"index" : "no",否则它仍将编入索引。

答案 1 :(得分:1)

  

我会假设一个字段是" not_analyzed"没有索引

这是一个容易做出的假设,但也是一个不正确的假设。在ES中,' not_analyzed'表示该字段中的数据未拆分为令牌(分析)。数据仍然被编入索引。

在ES中搜索的最快方法是使用filters。从第一个查询DSL页面:

  

过滤器非常方便,因为它们比普通查询执行的数量级更好,因为不执行任何评分并且它们会自动缓存。

由于过滤器速度快得多,因此最快的查询几乎总是过滤查询:

{
    "query": {
        "filtered": {
            "query": { 'match_all' : { } },
            "filter": {
                { "term": { "owner": 123 }}
            }
        }
    }
}

Filtered Query页面所述,过滤查询的默认查询为match_all,因此此查询可以进一步缩短为:

{
    "query": {
        "filtered": {
            "filter": {
                { "term": { "owner": 123 }}
            }
        }
    }
}

过滤器的限制是它们是布尔值。两种文档都与过滤器完全匹配,或者不匹配。为了提高性能,建议尽可能使用过滤器进行约束,然后使用查询进行进一步匹配。

我构建了一个查询构建器,用于解析HTML表单,然后提交搜索参数。构建器检查每个搜索参数是否存在通配符(?或*),如果存在,则使用通配符查询。如果没有,它会添加一个过滤器。我提供UI按钮,以便用户通过单击数据轻松执行精确搜索。当他们使用这些搜索时,搜索过滤器并且快速变坏。他们还可以在等待几毫秒后输入string*并得到他们想要的东西。

这是我的查询构建器的通用代码段:

var filters = [], queries = [];
var searchVal = ..., searchField = ...;

var getWild = function (field, val, boost) {
    var wc = { wildcard: { } };
    wc.wildcard[field] = { value: val, boost: (boost || 1) };
    return wc;
};

if (searchVal) {
    if (/\*|\?/.test(searchVal)) {
        queries.push(getWild(searchField, searchVal);
    }
    else {
        filters.push({ term: {searchField: searchVal}});
    }
}

我使用And过滤器来约束所有完全匹配(日期范围,uid约束等),然后将其余查询作为filtered -> bool查询。它运行得非常好,我的小型3节点ES集群有133,000,000个文档足够快。

答案 2 :(得分:0)

对于您的用例,relational features的es很有趣。这些允许查询has_parent,您可以在其中搜索确切的ID。除此之外,提到的term query是正确的。