查询弹性搜索(如 sql "having")
querying elastic search (like sql "having")
这是 table 的人以及他们说的语言。
我需要找只懂一种语言的人(隐藏),
测试它(英语和德语)
我想得到 (hid 3) 和 (hid 4)
PUT test/huml/1
{"hid":1,"lang":"eng"}
PUT test/huml/2
{"hid":1,"lang":"ger"}
PUT test/huml/3
{"hid":1,"lang":"fr"}
PUT test/huml/4
{"hid":2,"lang":"eng"}
PUT test/huml/5
{"hid":2,"lang":"jap"}
PUT test/huml/6
{"hid":3,"lang":"eng"}
PUT test/huml/7
{"hid":4,"lang":"ger"}
PUT test/huml/8
{"hid":5,"lang":"eng"}
PUT test/huml/9
{"hid":5,"lang":"ger"}
PUT test/huml/10
{"hid":6,"lang":"eng"}
PUT test/huml/111
{"hid":6,"lang":"jap"}
在 Oracle 中 sql 这将像这样完成:
with
t as (
select 1 hid, 'eng' l from dual union all
select 1, 'ger' from dual union all
select 1, 'fr' from dual union all
select 2, 'eng' from dual union all
select 2, 'jap' from dual union all
select 3, 'eng' from dual union all
select 4, 'ger' from dual union all
select 5, 'eng' from dual union all
select 5, 'ger' from dual union all
select 6, 'eng' from dual union all
select 6, 'jap' from dual
)
select hid,max(l)
from t
group by hid,l
having count (distinct case when l in ('eng','ger') then l end) = 1
and count(1) =1
我认为还没有办法直接完成您的要求(尽管请参阅 GitHub 问题 here and here). You could probably hack something together with a scripted metric aggregation,尽管这也不是很理想(而且我假设不会很好地扩展,虽然我没有尝试过)。
根据您发布的内容,可以很容易地找出有多少 种语言的用户:
POST /test_index/_search?search_type=count
{
"aggs": {
"humans": {
"terms": { "field": "hid" },
"aggs": {
"num_of_langs": {
"value_count": { "field": "lang" }
}
}
}
}
}
但这似乎并不是你真正要问的。
不过,如果稍微修改架构,则可以(或多或少)结合使用 bool and has_child 个过滤器来解决问题。这是一种方法。
我获取了您发布的文档,并为每个 "hid"
提取了 "parent" 个对象。我使用了一个建立父子关系的映射,然后批量索引文档:
DELETE /test_index
PUT /test_index
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"human": {
"properties": {
"hid": { "type": "long" }
}
},
"has_lang": {
"_parent": { "type": "human" },
"properties": {
"hid": { "type": "long" },
"lang": { "type": "string" }
}
}
}
}
PUT /test_index/_bulk
{"index":{"_index":"test_index", "_type":"human", "_id":1}}
{"hid":1}
{"index":{"_index":"test_index", "_type":"human", "_id":2}}
{"hid":2}
{"index":{"_index":"test_index", "_type":"human", "_id":3}}
{"hid":3}
{"index":{"_index":"test_index", "_type":"human", "_id":4}}
{"hid":4}
{"index":{"_index":"test_index", "_type":"human", "_id":5}}
{"hid":5}
{"index":{"_index":"test_index", "_type":"human", "_id":6}}
{"hid":6}
PUT /test_index/_bulk
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":1, "_id":1}}
{"hid":1,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":1, "_id":2}}
{"hid":1,"lang":"ger"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":1, "_id":3}}
{"hid":1,"lang":"fr"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":2, "_id":4}}
{"hid":2,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":2, "_id":5}}
{"hid":2,"lang":"jap"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":3, "_id":6}}
{"hid":3,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":4, "_id":7}}
{"hid":4,"lang":"ger"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":5, "_id":8}}
{"hid":5,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":5, "_id":9}}
{"hid":5,"lang":"ger"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":6, "_id":10}}
{"hid":6,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":6, "_id":11}}
{"hid":6,"lang":"jap"}
然后我可以查询说特定语言但不说其他语言的人,如下所示:
POST /test_index/human/_search
{
"filter": {
"bool": {
"must": [
{
"has_child": {
"type": "has_lang",
"filter": { "term": { "lang": "ger" } }
}
}
],
"must_not": [
{
"has_child": {
"type": "has_lang",
"filter": {
"not": {
"filter": { "term": { "lang": "ger" } }
}
}
}
}
]
}
}
}
...
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "human",
"_id": "4",
"_score": 1,
"_source": {
"hid": 4
}
}
]
}
}
您仍然需要为每种语言执行此操作,因此此方法可能并不理想,但希望它能让您更接近。
我也尝试过使用聚合来获得你想要的答案,但从未找到让它发挥作用的方法。 If/when reducer 聚合得到实现,如果我理解正确的话,这大概会解决这类问题。
这是我使用的代码:
http://sense.qbox.io/gist/0615ec52346ae6e547988b156b221484dbfde50c
这是 table 的人以及他们说的语言。 我需要找只懂一种语言的人(隐藏), 测试它(英语和德语) 我想得到 (hid 3) 和 (hid 4)
PUT test/huml/1
{"hid":1,"lang":"eng"}
PUT test/huml/2
{"hid":1,"lang":"ger"}
PUT test/huml/3
{"hid":1,"lang":"fr"}
PUT test/huml/4
{"hid":2,"lang":"eng"}
PUT test/huml/5
{"hid":2,"lang":"jap"}
PUT test/huml/6
{"hid":3,"lang":"eng"}
PUT test/huml/7
{"hid":4,"lang":"ger"}
PUT test/huml/8
{"hid":5,"lang":"eng"}
PUT test/huml/9
{"hid":5,"lang":"ger"}
PUT test/huml/10
{"hid":6,"lang":"eng"}
PUT test/huml/111
{"hid":6,"lang":"jap"}
在 Oracle 中 sql 这将像这样完成:
with
t as (
select 1 hid, 'eng' l from dual union all
select 1, 'ger' from dual union all
select 1, 'fr' from dual union all
select 2, 'eng' from dual union all
select 2, 'jap' from dual union all
select 3, 'eng' from dual union all
select 4, 'ger' from dual union all
select 5, 'eng' from dual union all
select 5, 'ger' from dual union all
select 6, 'eng' from dual union all
select 6, 'jap' from dual
)
select hid,max(l)
from t
group by hid,l
having count (distinct case when l in ('eng','ger') then l end) = 1
and count(1) =1
我认为还没有办法直接完成您的要求(尽管请参阅 GitHub 问题 here and here). You could probably hack something together with a scripted metric aggregation,尽管这也不是很理想(而且我假设不会很好地扩展,虽然我没有尝试过)。
根据您发布的内容,可以很容易地找出有多少 种语言的用户:
POST /test_index/_search?search_type=count
{
"aggs": {
"humans": {
"terms": { "field": "hid" },
"aggs": {
"num_of_langs": {
"value_count": { "field": "lang" }
}
}
}
}
}
但这似乎并不是你真正要问的。
不过,如果稍微修改架构,则可以(或多或少)结合使用 bool and has_child 个过滤器来解决问题。这是一种方法。
我获取了您发布的文档,并为每个 "hid"
提取了 "parent" 个对象。我使用了一个建立父子关系的映射,然后批量索引文档:
DELETE /test_index
PUT /test_index
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"human": {
"properties": {
"hid": { "type": "long" }
}
},
"has_lang": {
"_parent": { "type": "human" },
"properties": {
"hid": { "type": "long" },
"lang": { "type": "string" }
}
}
}
}
PUT /test_index/_bulk
{"index":{"_index":"test_index", "_type":"human", "_id":1}}
{"hid":1}
{"index":{"_index":"test_index", "_type":"human", "_id":2}}
{"hid":2}
{"index":{"_index":"test_index", "_type":"human", "_id":3}}
{"hid":3}
{"index":{"_index":"test_index", "_type":"human", "_id":4}}
{"hid":4}
{"index":{"_index":"test_index", "_type":"human", "_id":5}}
{"hid":5}
{"index":{"_index":"test_index", "_type":"human", "_id":6}}
{"hid":6}
PUT /test_index/_bulk
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":1, "_id":1}}
{"hid":1,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":1, "_id":2}}
{"hid":1,"lang":"ger"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":1, "_id":3}}
{"hid":1,"lang":"fr"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":2, "_id":4}}
{"hid":2,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":2, "_id":5}}
{"hid":2,"lang":"jap"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":3, "_id":6}}
{"hid":3,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":4, "_id":7}}
{"hid":4,"lang":"ger"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":5, "_id":8}}
{"hid":5,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":5, "_id":9}}
{"hid":5,"lang":"ger"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":6, "_id":10}}
{"hid":6,"lang":"eng"}
{"index":{"_index":"test_index", "_type":"has_lang", "_parent":6, "_id":11}}
{"hid":6,"lang":"jap"}
然后我可以查询说特定语言但不说其他语言的人,如下所示:
POST /test_index/human/_search
{
"filter": {
"bool": {
"must": [
{
"has_child": {
"type": "has_lang",
"filter": { "term": { "lang": "ger" } }
}
}
],
"must_not": [
{
"has_child": {
"type": "has_lang",
"filter": {
"not": {
"filter": { "term": { "lang": "ger" } }
}
}
}
}
]
}
}
}
...
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "human",
"_id": "4",
"_score": 1,
"_source": {
"hid": 4
}
}
]
}
}
您仍然需要为每种语言执行此操作,因此此方法可能并不理想,但希望它能让您更接近。
我也尝试过使用聚合来获得你想要的答案,但从未找到让它发挥作用的方法。 If/when reducer 聚合得到实现,如果我理解正确的话,这大概会解决这类问题。
这是我使用的代码:
http://sense.qbox.io/gist/0615ec52346ae6e547988b156b221484dbfde50c