【问题标题】:Elastic Search, from-start doesn't work correctly弹性搜索,从头开始无法正常工作
【发布时间】:2018-09-11 15:12:25
【问题描述】:

我将使用 Elastic Search 查询在两个日期之间获取一些记录。

首先,我检查两个日期之间的记录数是否大于 10000。如果是,我会尝试以 10000 乘以 10000 的方式获取它们。

    //get count
    var result_count = client.Count<TelegramMessageStructure>(s => s
    .AllTypes()
    .AllIndices()
    .Query(q => q
    .DateRange(r => r
    .Field(f => f.messageDate)
    .GreaterThanOrEquals("2018-06-03 00:00:00.000")
    .LessThan("2018-06-03 00:59:00.000")
    )
    )
    );
    long count = result_count.Count; //count = 27000

它返回 27000。所以我想用 10000 乘以 10000 来获取它们。我使用这个查询来做到这一点:

    int MaxMessageCountPerQuery=10000;

    for (int i = 0; i < count; i += MaxMessageCountPerQuery)
    {
        client = new ElasticClient(connectionSettings);
        // No change whether the client is renewed or not
        var result = client.Search<TelegramMessageStructure>(s => s
           .AllTypes()
           .AllIndices()
           .MatchAll()
           .From(i)
           .Size(MaxMessageCountPerQuery)
           .Sort(ss => ss.Ascending(p => p.id))
           .Query(q => q
               .DateRange(r => r
                   .Field(f => f.messageDate)
                   .GreaterThanOrEquals("2018-06-03 00:00:00.000")
                   .LessThan("2018-06-03 00:59:00.000")
               )
           )
       );
       //when i=0, result.documents contains 10000 records otherwise it has 0

    }

第一轮,当i=0时,result.documents包含10000条记录,否则为0条记录。

这有什么问题?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    基于此链接: scroll in elastic net-api

    您的代码应包含以下步骤:

    1- 使用您需要的所有参数以及 .Scroll("5m") 进行搜索(我假设 from(0)size(10000) 也已设置并将响应保存在 result 变量中)

    2- 现在您有前 10000 条记录(在 result.Documents 中)

    3- 要接收更多记录,您应该使用 ScrollId 参数来获得更多结果。 (每次调用下面的代码都会给你接下来的 10000 条记录)

    var result_new = client.Scroll<TelegramMessageStructure>("10m", result.ScrollId);
    

    其实你的代码应该是这样的:

            int MaxMessageCountPerQuery=10000;
    
            client = new ElasticClient(connectionSettings);
            // No change whether the client is renewed or not
            var result = client.Search<TelegramMessageStructure>(s => s
               .AllTypes()
               .AllIndices()
               .MatchAll()
               .From(i)
               .Size(MaxMessageCountPerQuery)
               .Sort(ss => ss.Ascending(p => p.id))
               .Query(q => q
                   .DateRange(r => r
                       .Field(f => f.messageDate)
                       .GreaterThanOrEquals("2018-06-03 00:00:00.000")
                       .LessThan("2018-06-03 00:59:00.000")
                   )
               )
               .Scroll("5m") // Add this parameter
           );
    
           // TODO some code:
           // save and use result.Documents
    
          for (int i = 0; i < result.Total; i += MaxMessageCountPerQuery)
          {
             var result_new = client.Scroll<TelegramMessageStructure>("10m", result.ScrollId); // Add this line to loop , Each loop you can get next 10000 record.
             // TODO some code:
             // save and use result_new.Documents
          }
    

    【讨论】:

      【解决方案2】:

      Elasticsearch 有一个默认 index.max_result_window = 10000 并且在 https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.html

      要了解为什么深度分页会出现问题,让我们假设我们 正在使用五个主分片的单个索引中进行搜索。什么时候我们 请求结果的第一页(结果 1 到 10),每个分片 生成自己的前 10 个结果并将它们返回给协调 节点,然后对所有 50 个结果进行排序以选择整体 前 10 名。

      现在假设我们要求第 1,000 页 - 结果 10,001 到 10,010。 一切都以相同的方式工作,除了每个分片必须产生 它的前 10,010 个结果。然后协调节点对所有 50,050 个结果并丢弃其中的 50,040 个!

      您可以看到,在分布式系统中,排序结果的成本 我们页面越深入,它就会呈指数增长。有一个很好的理由 网络搜索引擎不会为任何查询返回超过 1,000 个结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-02
        • 2019-08-04
        • 2021-11-10
        • 2017-01-28
        • 2013-12-23
        相关资源
        最近更新 更多