还有一个情况下,我们需要帮助ElasticSearch了解我们的数据结构,以便能够充分进行查询 - 复杂对象数组的时候。
按理说的ElasticSearch的最佳功能之一是,它使我们能够索引和搜索之间复杂的JSON对象。我们不局限于领域的平面列表,但可以与对象图工作,就像我们使用面向对象语言编程时。
然而,有一种情况,我们需要帮助ElasticSearch了解我们的数据结构,以便能够充分进行查询 - 复杂对象数组的时候。
作为一个例子,看看下面的分度的要求,我们的索引电影,包括在由演员第一次复杂的对象和姓氏的形式演员列表:
curl -XPOST "http://localhost:9200/index-1/movie/" -d' { "title": "The Matrix", "cast": [ { "firstName": "Keanu", "lastName": "Reeves" }, { "firstName": "Laurence", "lastName": "Fishburne" } ] }'
鉴于许多这样的电影在我们的索引,我们可以找到一个名为“基努”使用搜索请求如演员的所有电影:
curl -XPOST "http://localhost:9200/index-1/movie/_search" -d' { "query": { "filtered": { "query": { "match_all": {} }, "filter": { "term": { "cast.firstName": "keanu" } } } } }'
运行上面的查询返回确实矩阵。如果我们试图找到与该名字“基努”和姓“里夫斯”一个演员的电影也是如此:
curl -XPOST "http://localhost:9200/index-1/movie/_search" -d' { "query": { "filtered": { "query": { "match_all": {} }, "filter": { "bool": { "must": [ { "term": { "cast.firstName": "keanu" } }, { "term": { "cast.lastName": "reeves" } } ] } } } } }'
或者至少看起来是这样。然而,让我们看看如果我们寻找电影与“基努”的名字和“菲什伯恩”作为姓氏的演员会发生什么。
curl -XPOST "http://localhost:9200/index-1/movie/_search" -d' { "query": { "filtered": { "query": { "match_all": {} }, "filter": { "bool": { "must": [ { "term": { "cast.firstName": "keanu" } }, { "term": { "cast.lastName": "fishburne" } } ] } } } } }'
显然,这应该,乍看之下,不匹配的矩阵有没有这样的演员之间的转换。然而,ElasticSearch将返回的Matrix上面的查询。毕竟,这部电影确实包含一个作家与“基努”作为第一个名称和(尽管是不同的)与“菲什伯恩”男主角为姓。基于上面的查询它有没有知道,我们希望两个词过滤器在演员名单匹配相同的唯一对象的方式。即使它确实,该数据被索引的方式,将不能够处理该要求。
嵌套映射和过滤救援
幸运的是ElasticSearch为我们提供能够在阵列中的相同对象中的多个字段进行过滤的方法; 测绘等领域的嵌套。尝试了这一点,让我们创建自己有映射为嵌套在“演员”领域的新指标。
curl -XPUT "http://localhost:9200/index-2" -d' { "mappings": { "movie": { "properties": { "cast": { "type": "nested" } } } } }'
索引同一部电影文件到新的指数,我们现在可以通过使用嵌套过滤器找到根据每个演员的多个属性短片后。下面是我们如何将搜索主演的电影名为“基努·菲什伯恩”演员:
curl -XPOST "http://localhost:9200/index-2/movie/_search" -d' { "query": { "filtered": { "query": { "match_all": {} }, "filter": { "nested": { "path": "cast", "filter": { "bool": { "must": [ { "term": { "firstName": "keanu" } }, { "term": { "lastName": "fishburne" } } ] } } } } } } }'
正如你可以看到我们包裹我们的一个嵌套过滤器的初始布尔过滤器。嵌套过滤器包含一个路径,我们指定过滤器适用于搜索的文档的演员财产一样。它还包含一个过滤器(或查询),其中将嵌套属性内被应用于每个值。
正如预期,在运行的Abobe查询没有返回矩阵,同时修改它,而不是匹配“里维斯”作为姓氏将使其匹配的矩阵。然而,有一点需要注意。
其中包括父文件嵌套值
如果我们回到我们的第一个查询,而无需使用嵌套过滤器,如下面的要求,就只有演员筛选的名字,我们不会得到任何命中。
curl -XPOST "http://localhost:9200/index-2/movie/_search" -d' { "query": { "filtered": { "query": { "match_all": {} }, "filter": { "term": { "cast.firstName": "keanu" } } } } }'
这是因为电影文件不再有cast.firstName领域。相反,投数组中的每个元素,在内部ElasticSearch,索引为一个单独的文件。
很显然,我们仍然可以搜索仅根据投之中名字的电影,但是通过使用嵌套过滤器。喜欢这个:
curl -XPOST "http://localhost:9200/index-2/movie/_search" -d' { "query": { "filtered": { "query": { "match_all": {} }, "filter": { "nested": { "path": "cast", "filter": { "term": { "firstName": "keanu" } } } } } } }'
上述请求返回的矩阵。然而,有时不得不使用嵌套过滤器或查询时,所有我们想要做的是过滤器上的单个属性是有点乏味。为了能够利用复杂的审核规定,同时仍然能够以同样的方式对价值筛选阵列嵌套滤波器的功率如果我们没有映射这些性能嵌套我们可以修改我们的映射,以便嵌套值也将是包括父文档英寸 这是使用进行include_in_parent财产,是这样的:
curl -XPUT "http://localhost:9200/index-3" -d' { "mappings": { "movie": { "properties": { "cast": { "type": "nested", "include_in_parent": true } } } } }'
在索引如与上述请求创建的我们俩能够使用嵌套滤波器,同时仍然能够在单个字段进行过滤,而无需使用嵌套滤波器演员阵列在相同的复杂对象内对值的组合进行筛选。 但是,我们现在需要认真考虑在何处使用,并在不使用,在我们的嵌套查询过滤器作为“基努·菲什伯恩”的查询将同时不会在包装时使用的是常规的布尔过滤器相匹配的矩阵嵌套过滤器。 换句话说,使用include_in_parent时候我们可能会得到意想不到的结果,由于匹配,它不应该,如果我们忘记使用嵌套过滤器文档的查询。