我有2个索引:
users
navigations
假设users
看起来像这样:
{
"properties": {
"cookies": {"type": "keyword"},
"name": {"type": "text"}
}
}
而且navigations
是这样的:
{
"properties": {
"url": {"type": "keyword"},
"cookie_id": {"type": "keyword"}
}
}
如您所见,users
并且navigations
可以通过cookie_id
和cookies
字段连接在一起。
实际上,我的索引有更多字段,但是只有这些字段才可以证明我的问题。
我存储users
并navigations
在2个不同的指标,而不是使用join
映射或nested
映射,因为我有更多的navigations
不是用户,并在我的大部分搜索使用情况下,我会只搜索users
,所以我不想保持列表navigations
每个users
。我更喜欢将它们分开(我还有其他一些约束,促使我选择2个单独的索引,例如数据协调等)。
我想做的是这样的查询/汇总:“给我所有在name
Fabien
那浏览了5次的用户url
http://example.com
”
到目前为止,我进行了以下查询/汇总(搜索查询是在我的2个索引上完成的):
POST /用户,导航/ _搜索
{
"query": {
"bool": {
"must": [
{"match": {"name": "Fabien"}}
]
}
},
"aggregations": {
"all_navs": {
"global": {},
"aggregations": {
"cookies": {
"terms": {"field": "cookie_id"},
"aggregations": {
"page_visited": {
"filter": {
"bool": {
"must": [
{"term": {"url": "http://example.com"} }
]
}
},
"aggregations": {
"number_page_visited": {
"value_count": {"field": "type"}
}
}
},
"count_filter": {
"bucket_selector": {
"buckets_path": {
"count": "page_visited>number_page_visited"
},
"script": "params.count > 5"
}
}
}
}
}
}
}
}
通过这个查询,我可以用过滤我users
的name = Fabien
,并且我可以cookie_id
从navigations
至少有5个文档的地方获取值url = http://example.com
。
但是我不知道如何使用cookie_id
聚合中的s过滤我的users
。
任何想法?
谢谢!
由于elasticsearch不是关系数据库,因此您将无法在单个请求中检索结果。这是Elasticsearch的强大局限性,但也是其出色表现的主要原因。
基本上,elasticsearch会将您的查询编译为Lucene查询,并使用Lucene查询执行索引扫描。没有一种机制可以使查询中的某些参数(例如,user_id
字段的值)依赖于另一个查询的结果(例如,id
从users
名称为“ Fabien”的地方查找所有值)。
您将必须在外部执行连接:
首先,从users
名称为的索引中检索所有文档Fabien
。如果文档数量不受限制,则必须执行滚动搜索或使用search_after
第二,从索引navigation
中检索所有文件,这些索引user_id
位于第一个请求返回的文档集中的位置,并且满足您的其他条件。
这种方法可能很慢,并且不能保证在运行第二个查询时用户索引尚未更新。
实际上,如果您使用联接类型映射,则无需在用例中使用聚合。
请注意,join字段有几个限制,不建议将其作为对一对多关系建模的默认解决方案。
这是一个可以满足您的要求的工作示例。
映射:包含用户和导航字段以及一个连接字段。
PUT /user_navigation
{
"mappings": {
"properties": {
"cookies": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"join_field": {
"type": "join",
"relations": {
"user": "navigation"
}
}
}
}
}
添加一些测试文档。两个父文档有个,name: Fabien
但只有一个有两个孩子cookies: http://example.com
。另一个文档有两个子对象,cookies: http://example.com
但没有以命名Fabien
。
POST user_navigation/_doc/_bulk
{ "index" : { "_index" : "user_navigation", "_id" : "1" } }
{ "name" : "Fabien", "join_field": "user" }
{ "index" : { "_index" : "user_navigation", "_id" : "2" } }
{ "name" : "Fabien", "join_field": "user" }
{ "index" : { "_index" : "user_navigation", "_id" : "3" } }
{ "name" : "Autre", "join_field": "user" }
{ "index" : { "_index" : "user_navigation", "routing": "1" } }
{ "cookies": "http://example.com", "join_field": { "name": "navigation", "parent": "1" }}
{ "index" : { "_index" : "user_navigation", "routing": "1"} }
{ "cookies": "http://example.com", "join_field": { "name": "navigation", "parent": "1" }}
{ "index" : { "_index" : "user_navigation", "routing": "2"} }
{ "cookies": "http://example.com", "join_field": { "name": "navigation", "parent": "2" }}
{ "index" : { "_index" : "user_navigation", "routing": "2"} }
{ "cookies": "other_url", "join_field": { "name": "navigation", "parent": "3" }}
{ "index" : { "_index" : "user_navigation", "routing": "3"} }
{ "cookies": "http://example.com", "join_field": { "name": "navigation", "parent": "3" }}
{ "index" : { "_index" : "user_navigation", "routing": "3"} }
{ "cookies": "http://example.com", "join_field": { "name": "navigation", "parent": "3" }}
以下请求使用has_child查询,并将仅返回带有name: Fabien
和的文档,这样它至少具有两个带有的子文档cookies: http://example.com
。
GET user_navigation/_doc/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"name": "Fabien"
}
},
{
"has_child": {
"type": "navigation",
"query": {
"term": {
"cookies": "http://example.com"
}
},
"min_children": 2,
"inner_hits": {}
}
}
]
}
}
}
响应将仅包含ID为1的文档。
"min_children"
参数允许更改必须满足请求的子文档的最小数量。
"inner_hits": {}
允许在响应中检索子文档。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句