假设我在用户/数据中有一个用户对象:
{"_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比较)才能得出结果。这对我来说是不可接受的 - 我需要它作为索引搜索。
答案 0 :(得分:2)
您可以在宠物身上使用term query
:http://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是正确的。