繁体   English   中英

如何使用ElasticSearch和/或Apache Solr表达异常查询?

[英]How to express an unusual query using ElasticSearch and/or Apache Solr?

在以下情况下如何查询索引。

文档具有以下属性:

body: # text
shares: # array of share(s)
    share:
        orgid: # text
        role: # text

以下是一些示例文档:

docs = [
    {'body':'hello', 'shares':[{'orgid':'abc.de.1', 'role':'11'}, 
                                       {'orgid':'abc', 'role':'1'}]},
    {'body':'world', 'shares':[{'orgid':'abc.de', 'role':'111'}]},
    {'body':'today', 'shares':[{'orgid':'abc', 'role':'111'}]}
]

使用ElasticSearch语法,我要执行以下查询:

Give me all docs where prefix of 'shares.orgid' = 'abc' and prefix of shares.role = '11'
    Should return: all of them
Give me all docs where prefix of 'shares.orgid' = 'abc.de' and prefix of shares.role = '111'
    Should return: world
Give me all docs where prefix of 'shares.orgid' = 'abc.de.1' and prefix of shares.role = '11'
    Should return: nothing
Give me all docs where prefix of 'shares.orgid' = 'abc' and prefix of shares.role = '111'
    Should return: world, today

当我对此进行研究时,发现了以下有趣的信息

特别是: ElasticSearch

ElasticSearch使您可以使用两种类型的查询– has_children和top_children查询对子文档进行操作。 第一个查询接受以ElasticSearch Query DSL表示的查询以及子类型,它会导致所有子文档与给定查询匹配的父文档。 第二类查询针对一定数量的子文档运行,然后将它们汇总到父文档中。 我们还可以为第二种查询类型选择得分计算。

同样感兴趣的是: http : //www.elasticsearch.org/guide/reference/query-dsl/has-child-query.html

有关重新编制索引的更多信息: http : //www.elasticsearch.org/guide/reference/api/index_.html父母与子女

可以在建立索引时通过指定子文档的父文档来建立索引。 例如:

$ curl -XPUT localhost:9200/blogs/blog_tag/1122?parent=1111 -d '{
    "tag" : "something"
}'

为子文档建立索引时,除非使用routing参数明确指定了路由值,否则路由值将自动设置为与父文档相同。

编辑:

我越来越近了。 这是一个我尝试使用包装器的测试,演示了一种方法。 我将编写一个测试来演示该问题的解决方案。 https://github.com/aparo/pyes/blob/master/tests/test_nested.py 我运行了该测试,并对其进行了调整以使用PrefixQuery,它可以工作。

对于每个评论者javanna,子查询都不是前进的方向。 这是使用pyes的示例摘录:

from pyes.filters import TermFilter, NestedFilter
from pyes.query import FilteredQuery, MatchAllQuery, BoolQuery, TermQuery, PrefixQuery



# from their unit test setup
self.conn.index({"field1": "value1",
                 "nested1": [{"n_field1": "n_value1_1",
                              "n_field2": "n_value2_1"},
                         {"n_field1": "n_value1_2",
                          "n_field2": "n_value2_2"}]},
    self.index_name, self.document_type, 1)
self.conn.index({"field1": "value1",
                 "nested1": [{"n_field1": "n_value1_1",
                              "n_field2": "n_value2_2"},
                         {"n_field1": "n_value1_2",
                          "n_field2": "n_value2_1"}]},
    self.index_name, self.document_type, 2)

self.conn.index({"field1": "value1",
                 "nested1": [{"n_field1": "ni",
                              "n_field2": "11"},
                         {"n_field1": "n_value1_2",
                          "n_field2": "n_value2_1"}]},
    self.index_name, self.document_type, 3)

self.conn.index({"field1": "value1",
                 "nested1": [{"n_field1": "ni.kirmse.104",
                              "n_field2": "111"},
                         {"n_field1": "n_value1_2",
                          "n_field2": "n_value2_1"}]},
    self.index_name, self.document_type, 4)

self.conn.refresh(self.index_name)


# just hacked their test to quickly see if I could do a prefix query on beginning of nested array/list values.

q = FilteredQuery(MatchAllQuery(),
    NestedFilter('nested1',
        BoolQuery(must=[PrefixQuery('nested1.n_field1', 'ni'),
                        PrefixQuery('nested1.n_field2', '111')])))
resultset = self.conn.search(query=q, indices=self.index_name, doc_types=[self.document_type])

好的,我找到了使用pyes(一种Python的Elasticsearch包装器)来执行此操作的方法。

我在这里获取了他们的测试之一: https : //github.com/aparo/pyes/blob/master/tests/test_nested.py

为了回答这个问题,我修改了测试以演示如何实现目标。

class NestedSearchTestCase(ESTestCase):
    def setUp(self):
        super(NestedSearchTestCase, self).setUp()

        mapping = {
            'shares': {
                'type': 'nested'
            }
        }
        self.conn.create_index(self.index_name)
        self.conn.put_mapping(self.document_type, {'properties': mapping}, self.index_name)
        self.conn.index({"body": "hello",
                         "shares": [{"orgid": "abc.de.1",
                                      "role": "11"},
                                    {"orgid": "abc",
                                      "role": "1"}]},
                        self.index_name, self.document_type, 1)

        self.conn.index({"body": "world",
                         "shares": [{"orgid": "abc.de",
                                      "role": "111"}]},
                        self.index_name, self.document_type, 2)

        self.conn.index({"body": "today",
                         "shares": [{"orgid": "abc",
                                      "role": "111"}]},
                        self.index_name, self.document_type, 3)

        self.conn.refresh(self.index_name)

    def test_nested_filter(self):
        q = FilteredQuery(MatchAllQuery(),
            NestedFilter('shares',
                BoolQuery(must=[PrefixQuery('shares.orgid', 'abc'),
                                PrefixQuery('shares.role', '11')])))
        resultset = self.conn.search(query=q, indices=self.index_name, doc_types=[self.document_type])
        self.assertEquals(resultset.total, 3)
        # prints: hello, world, today
        print ', '.join([r['body'] for r in resultset])


        q = FilteredQuery(MatchAllQuery(),
            NestedFilter('shares',
                BoolQuery(must=[PrefixQuery('shares.orgid', 'abc.de'),
                                PrefixQuery('shares.role', '111')])))
        resultset = self.conn.search(query=q, indices=self.index_name, doc_types=[self.document_type])
        self.assertEquals(resultset.total, 1)
        # prints: world
        print ', '.join([r['body'] for r in resultset])


        q = FilteredQuery(MatchAllQuery(),
            NestedFilter('shares',
                BoolQuery(must=[PrefixQuery('shares.orgid', 'abc.de.1'),
                                PrefixQuery('shares.role', '11')])))
        resultset = self.conn.search(query=q, indices=self.index_name, doc_types=[self.document_type])
        self.assertEquals(resultset.total, 0)
        # prints: nothing
        print ', '.join([r['body'] for r in resultset])


        q = FilteredQuery(MatchAllQuery(),
            NestedFilter('shares',
                BoolQuery(must=[PrefixQuery('shares.orgid', 'abc'),
                                PrefixQuery('shares.role', '111')])))
        resultset = self.conn.search(query=q, indices=self.index_name, doc_types=[self.document_type])
        self.assertEquals(resultset.total, 2)
        # prints: world, today
        print ', '.join([r['body'] for r in resultset])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM