2015-05-04 186 views
0

我正面临提供具有多级别层次结构的文档的聚合搜索结果的问题。简化文档结构如下:(二)Elasticsearch - 聚合多级别层次结构

杂志标题(狩猎) - - >杂志一年(1999年)>杂志发行 - >页面(页面的文本......)

每个级别od文档通过属性“parentDocumentId”映射到其父级。

我已经准备了简单的查询,这对于层次结构工程只是罚款只有2级:

POST http://localhost:9200/my_index/document/_search?search_type=count&q=hunter 
{ 
    "query": { 
    "multi_match" : { 
     "query": "hunter", 
     "fields": [ "title", "text", "labels" ] 
    } 
    }, 
    "aggregations": { 
     "my_agg": { 
     "terms": { 
      "field": "parentDocumentId" 
     } 
     } 
    } 
} 

这种查询可以通过网页的文字进行搜索,并给了我几千containting工作页istead “猎人”返回文档的桶(由parentDocumentId聚合)。然而这些桶只代表“杂志问题”其中包含这些页面。

响应:

{ 
    "took": 54, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 44, 
     "max_score": 0, 
     "hits": [] 
    }, 
    "aggregations": { 
     "my_agg": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
      { 
       "key": 5, 
       "doc_count": 43 
      }, 
      { 
       "key": 0, 
       "doc_count": 1 
      } 
     ] 
     } 
    } 
} 

我需要什么,是为了能够在尽可能高的水平聚合搜索结果。这意味着,在这种特殊情况下,聚合“杂志标题”级别。这可以在弹性搜索查询之外完成(在我们的应用程序一侧),但正如我看到的那样,它肯定是在elasticsearch(性能和其他问题)中完成的。

有没有人有类似聚合的经验? elasticsearch聚合是否正确使用?

每个想法都是值得欢迎的。

感谢 彼得

更新: 我们的映射是这样的:

{ 
    "my_index": { 
     "mappings": { 
     "document": { 
      "properties": { 
       "dateIssued": { 
        "type": "date", 
        "format": "dateOptionalTime" 
       }, 
       "documentId": { 
        "type": "long" 
       }, 
       "filter": { 
        "properties": { 
        "geo_bounding_box": { 
         "properties": { 
          "issuedLocation": { 
           "properties": { 
           "bottom_right": { 
            "properties": { 
             "lat": { 
              "type": "double" 
             }, 
             "lon": { 
              "type": "double" 
             } 
            } 
           }, 
           "top_left": { 
            "properties": { 
             "lat": { 
              "type": "double" 
             }, 
             "lon": { 
              "type": "double" 
             } 
            } 
           } 
           } 
          } 
         } 
        } 
        } 
       }, 
       "issuedLocation": { 
        "type": "geo_point" 
       }, 
       "labels": { 
        "type": "string" 
       }, 
       "locationLinks": { 
        "type": "geo_point" 
       }, 
       "parentDocumentId": { 
        "type": "long" 
       }, 
       "query": { 
        "properties": { 
        "match_all": { 
         "type": "object" 
        } 
        } 
       }, 
       "storedLocation": { 
        "type": "geo_point" 
       }, 
       "text": { 
        "type": "string" 
       }, 
       "title": { 
        "type": "string" 
       }, 
       "type": { 
        "type": "string" 
       } 
      } 
     } 
     } 
    } 
} 

这意味着我们需要用1个映射所有类型的文件。我们正在索引一套书,报纸和其他媒体。这意味着,有时一组页面只有一个父母,有时在页面级别以上有多个父母级别。

要区分文档的类型,有一个属性“类型”

当索引顶层(这些包含特别是书籍元数据)时,我们将“text”属性留空,始终使用parentDocumentId指定文档的父级。顶级文档的parentDocumentId设置为0.当索引最低级别(页面)时,我们仅为索引文档提供文本属性和parentDocumentId。

使用的链接非常类似于经典的一对多映射(杂志有很多年,有许多问题,有很多页面)。

你也可以说,我们已经在夷为平地的elasticsearch嵌套的文件,但这样做的原因是,有多种文档类型,可有不同程度的层次的。

+0

你可以张贴有完整的层次文档的一个具体的例子? (不一定具有所有的属性)。如果您还包含了映射,这将会很有帮助。就目前而言,您如何为文档编制索引完全不清楚。它是一个在Elasticsearch中被压平的嵌套文档吗?它是嵌套类型的嵌套文档吗?它是每个层次级别的一个文档,只是像在关系数据库中一样使用PK/FK对互相引用? –

+0

@jkbkot - 非常感谢您的评论。我已经更新了映射描述,并且还描述了这些文档是如何编制索引的。 – shimon001

回答

1

您需要重新考虑您的数据建模。实质上,您需要对数据进行连接,而且连接需要位于任意深度的层次结构中。即使在关系数据库中,这也是一个问题,更不用说像Elasticsearch这样的全文搜索引擎。

Elasticsearch确实支持一些连接。您可以使用嵌套文档 - 嵌套了所有子文档的单个文档。这显然不适合你的情况。

您可以使用parent-child relationship功能,该功能可让您将(子)文档分别索引至其父文件。在下面,该功能使用Lucene的blockjoin。但是,要聚合层次结构,您必须明确指定加入 - 列出所有中间步骤。您希望始终按照最高可用文档进行汇总,但每次都可能会有不同的级别(一次是杂志,另一次是杂志收集或可能是出版商)。

我会考虑用指向最顶端文档的字段为每个文档建立索引。那么你可以很容易地聚合该领域。这意味着要预先计算你想要做的复杂聚合的一部分,但这会导致快速聚合,更新也不会很痛苦。这一切都取决于数据的来源,你如何想象它会改变,你需要做什么更新和其他查询。

本博客文章能对您有所帮助有点太:https://www.elastic.co/blog/managing-relations-inside-elasticsearch

+0

非常感谢您的回复。我将尝试重新思考数据索引的方式。 – shimon001