簡體   English   中英

Elasticsearch對已排序的聚合結果進行分頁

[英]Elasticsearch paginating a sorted, aggregated result

據我所知,沒有辦法在Elasticsearch中執行以下操作:

SELECT * FROM myindex
GROUP BY agg_field1, agg_field2, agg_field3 // aggregation
ORDER BY order_field1, order_field2, order_field3 // sort
LIMIT 1000, 5000 // paginate -- get page 6 of size 1000 records

以下是一些有關此問題的相關文件:

有沒有辦法在Elasticsearch中執行上述操作? 我們的一個限制是我們永遠不會有超過10M的記錄,所以我們(希望)不應該遇到內存錯誤。 我的想法是這樣做:

  • 進行聚合查詢
  • 從中獲取結果數量
  • 根據我們想要的結果和頁面大小將其拆分為N個段
  • 使用上述段重新運行查詢

實現這一目標的最佳方法是什么? 在您的回答/建議中,您能否發布一些有關如何在ES中完成上述SQL查詢的示例代碼?


作為此問題的更新,這是一個公共索引,用於測試:

# 5.6
e=Elasticsearch('https://search-testinges-fekocjpedql2f3rneuagyukvy4.us-west-1.es.amazonaws.com')
e.search('testindex')

# 6.4 (same data as above)
e = Elasticsearch('https://search-testinges6-fycj5kjd7l5uyo6npycuashch4.us-west-1.es.amazonaws.com')
e.search('testindex6')

它有10,000條記錄。 隨意測試:

在此輸入圖像描述

我正在尋找的查詢如下(在sql中):

SELECT * FROM testindex
GROUP BY store_url, status, title
ORDER BY title ASC, status DESC
LIMIT 100 OFFSET 6000

換句話說,我希望對聚合結果(具有多個聚合)進行排序並獲得偏移量。

composite聚合可能在這里有所幫助,因為它允許您按多個字段進行分組,然后對結果進行分頁。 它不允許你做的唯一事情就是跳過一個給定的偏移量,但你可以通過從客戶端代碼迭代來做到這一點,如果有必要的話。

所以這是一個示例查詢:

POST testindex6/_search
{
  "size": 0,
  "aggs": {
    "my_buckets": {
      "composite": {
        "size": 100,
        "sources": [
          {
            "store": {
              "terms": {
                "field": "store_url"
              }
            }
          },
          {
            "status": {
              "terms": {
                "field": "status",
                "order": "desc"
              }
            }
          },
          {
            "title": {
              "terms": {
                "field": "title",
                "order": "asc"
              }
            }
          }
        ]
      },
      "aggs": {
        "hits": {
          "top_hits": {
            "size": 100
          }
        }
      }
    }
  }
}

在響應中你會看到和after_key結構:

  "after_key": {
    "store": "http://google.com1087",
    "status": "OK1087",
    "title": "Titanic1087"
  },

這是您需要在后續查詢中使用的某種游標,如下所示:

{
  "size": 0,
  "aggs": {
    "my_buckets": {
      "composite": {
        "size": 100,
        "sources": [
          {
            "store": {
              "terms": {
                "field": "store_url"
              }
            }
          },
          {
            "status": {
              "terms": {
                "field": "status",
                "order": "desc"
              }
            }
          },
          {
            "title": {
              "terms": {
                "field": "title",
                "order": "asc"
              }
            }
          }
        ],
        "after": {
          "store": "http://google.com1087",
          "status": "OK1087",
          "title": "Titanic1087"
        }
      },
      "aggs": {
        "hits": {
          "top_hits": {
            "size": 100
          }
        }
      }
    }
  }
}

它將為您提供接下來的100個桶。 希望這會有所幫助。

更新

如果你想知道總共會有多少桶,那么composite聚合將不會給你這個數字。 但是,由於composite聚合只不過是其來源中所有字段的笛卡爾積,您可以通過返回]基數]來獲得該總數的良好近似值( https://www.elastic.co/guide /en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.htmlcomposite聚合中使用的每個字段並將它們相乘。

  "aggs": {
    "my_buckets": {
      "composite": {
        ...
      }
    },
    "store_cardinality": {
      "cardinality": {
        "field": "store_url"
      }
    },
    "status_cardinality": {
      "cardinality": {
        "field": "status"
      }
    },
    "title_cardinality": {
      "cardinality": {
        "field": "title"
      }
    }
  }

然后我們可以通過將store_cardinalitystatus_cardinalitytitle_cardinality的數字相乘,或者至少得到一個很好的近似值來得到桶的總數(它在高基數字段上不能很好地工作,但在低基數上很好那些)。

現場崩潰就是答案。

當我們想要在特定字段上對命中進行分組時(如在agg_field中的組中),將使用字段折疊功能。

在Elastic 6之前,對字段進行分組的方法是使用聚合 這種方法缺乏高效分頁的能力。

但是現在,通過彈性提供開箱即用的場地坍塌,這很容易。

以下是從上面的鏈接獲取字段折疊的示例查詢。

GET /twitter/_search
{
  "query": {
      "match": {
          "message": "elasticsearch"
      }
  },
  "collapse" : {
      "field" : "user", 
      "inner_hits": {
          "name": "last_tweets", 
          "size": 5, 
          "sort": [{ "date": "asc" }] 
      },
      "max_concurrent_group_searches": 4 
  },
  "sort": ["likes"]

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM