Elasticsearch“get by index”返回文档,而“match_all”则不返回任何结果

时间:2016-09-14 13:57:53

标签: unit-testing python-3.x elasticsearch elasticsearch-py

我正在尝试模拟用于托管CI单元测试目的的elasticsearch数据。

我准备了一些我可以使用bulk()成功加载的灯具,但是,由于未知原因,我无法匹配任何,即使test_index似乎包含数据(因为我可以通过他们的ID get()项目。)

fixtures.json是我从实际生产索引中获取的ES文档的子集。使用真实世界索引,一切都按预期工作,所有测试都通过。

奇怪行为的一个人为例子如下:

class MyTestCase(TestCase):
    es = Elasticsearch()

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.es.indices.create('test_index', SOME_SCHEMA)

        with open('fixtures.json') as fixtures:
            bulk(cls.es, json.load(fixtures))

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        cls.es.indices.delete('test_index')

    def test_something(self):
        # check all documents are there:
        with open('fixtures.json') as fixtures:
            for f in json.load(fixtures):
                print(self.es.get(index='test_index', id=f['_id']))
                # yes they are!

        # BUT:
        match_all = {"query": {"match_all": {}}}
        print('hits:', self.es.search(index='test_index', body=match_all)['hits']['hits'])
        # prints `hits: []` like there was nothing in

        print('count:', self.es.count(index='test_index', body=match_all)['count'])
        # prints `count: 0`

2 个答案:

答案 0 :(得分:1)

虽然我可以完全理解你的痛苦(除了测试之外一切都有效),答案其实很简单:与你的实验相比,测试太快了。

  • Elasticsearch是near real-time搜索引擎,这意味着在那里 索引文档之间的延迟最多为1秒 搜索。
  • 还有不可预测的延迟(取决于实际情况 创建索引并准备就绪之间的开销。

所以修复将time.sleep()给ES一些空间来创建它所需的所有魔法来给你带来结果。我会这样做:

@classmethod
def setUpClass(cls):
    super().setUpClass()
    cls.es.indices.create('test_index', SOME_SCHEMA)

    with open('fixtures.json') as fixtures:
        bulk(cls.es, json.load(fixtures))

    cls.wait_until_index_ready()

@classmethod
def wait_until_index_ready(cls, timeout=10):
    for sec in range(timeout):
        time.sleep(1)
        if cls.es.cluster.health().get('status') in ('green', 'yellow'):
            break

答案 1 :(得分:1)

虽然@ jsmesami的答案非常正确,但这样做可能更为清晰。如果您注意到,问题是因为ES没有重新编入索引。实际上,为此目的,API实际上有一些功能。 尝试类似的事情,

cls.es.indices.flush(wait_if_ongoing=True)
cls.es.indices.refresh(index='*')

更具体地说,您可以将index='test_index'传递给这两个函数。我认为这比使用sleep(..)更清晰,更具体。