指定在使用 inner_hits 时为 ElasticSearch 查询返回的结果的总大小

mmc*_*aff 4 elasticsearch

ElasticSearch 允许 inner_hits 指定 'from' 和 'size' 参数,就像搜索的外部请求体一样。

例如,假设我的索引包含 25 本书,每本书少于 50 章。以下代码段将返回所有书籍的所有章节,因为 100 本书的“大小”包括所有 25 本书,而 50 章的“大小”包括“少于 50 章”的所有内容:

        "index": 'books',
        "type": 'book',
        "body": {
          "from" : 0, "size" : 100, // outer hits, or books
          "query": {
              "filtered": {
                "filter": {
                  "nested": {
                    "inner_hits": {
                      "size": 50 // inner hits, or chapters
                    },
                    "path": "chapter",
                    "query": { "match_all": { } }, 
                  }
                }
               }
            },
            .
            .
            .
Run Code Online (Sandbox Code Playgroud)

现在,我想用这样的场景实现分页。我的问题是,如何?

在这种情况下,我是否必须从搜索查询返回上述最大 100 * 50 = 5000 个文档并通过仅显示我感兴趣的切片在应用程序级别实现分页?或者,有没有办法指定在搜索查询本身中返回的总命中数,而与内部/外部大小无关?

我正在查看“响应”如下,因此希望能够对这些数据进行分页:

        response.hits.hits.forEach(function(book) {
           chapters = book.inner_hits.chapters.hits.hits;

           chapters.forEach(function(chapter) {
               // ... this is one displayed result ...
           });
        });
Run Code Online (Sandbox Code Playgroud)

And*_*fan 5

我认为 Elasticsearch 和nested字段不可能做到这一点。您查看结果的方式是正确的:ES 分页并返回books但在nestedinner_hits内部看不到。不是它的工作原理。您需要在代码中手动处理分页。

还有另一种选择,但您需要父/子关系而不是nested

然后,您可以查询子项(即章节)并对结果(章节)进行分页。您可以使用inner_hits并退回parent(书本身)。

PUT /library
{
  "mappings": {
    "book": {
      "properties": {
        "name": {
          "type": "string"
        }
      }
    },
    "chapter": {
      "_parent": {
        "type": "book"
      },
      "properties": {
        "title": {
          "type": "string"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

查询:

GET /library/chapter/_search
{
  "size": 5, 
  "query": {
    "has_parent": {
      "type": "book",
      "query": {
        "match_all": {}
      },
      "inner_hits" : {}
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

和一个示例输出(修剪,完整的例子在这里):

  "hits": [
     {
        "_index": "library",
        "_type": "chapter",
        "_id": "1",
        "_score": 1,
        "_source": {
           "title": "chap1"
        },
        "inner_hits": {
           "book": {
              "hits": {
                 "total": 1,
                 "max_score": 1,
                 "hits": [
                    {
                       "_index": "library",
                       "_type": "book",
                       "_id": "book1",
                       "_score": 1,
                       "_source": {
                          "name": "book1"
                       }
                    }
                 ]
              }
           }
        }
     },
     {
        "_index": "library",
        "_type": "chapter",
        "_id": "2",
        "_score": 1,
        "_source": {
           "title": "chap2"
        },
        "inner_hits": {
           "book": {
              "hits": {
                 "total": 1,
                 "max_score": 1,
                 "hits": [
                    {
                       "_index": "library",
                       "_type": "book",
                       "_id": "book1",
                       "_score": 1,
                       "_source": {
                          "name": "book1"
                       }
                    }
                 ]
              }
           }
        }
     }
Run Code Online (Sandbox Code Playgroud)