我正在使用这种映射(好吧,这是一个较短的版本,以使问题更容易)对一个孩子-父母关系,其中item
是parent
和user_items
是children
。
curl -XPUT 'localhost:9200/myindex?pretty=true' -d '{
"mappings": {
"items": {
"dynamic": "strict",
"properties" : {
"title" : { "type": "string" },
"body" : { "type": "string" },
}},
"user_items": {
"dynamic": "strict",
"_parent": {"type": "items" },
"properties" : {
"user_id" : { "type": "integer" },
"source_id" : { "type": "integer" },
}}}}'
和我通常做的查询类型:
curl -XGET 'localhost:9200/myindex/items/_search?pretty=true' -d '{
"query": {
"bool": {
"must": [
{
"query_string": {
"fields": ["title", "body"],
"query": "mercado"
}
},
{
"has_child": {
"type": "user_items",
"query": {
"term": {
"user_id": 655
}}}}]}}}'
在这个查询中,它必须在字段title
和body
上搜索字符串mercado
,在给定的user_id
上,在本例中是655
。
第一个查询非常慢,可能需要15秒。下面的代码非常快(<0.5秒)
我读到第一个查询如此慢的原因是它被缓存,然后其余查询很快,因为它与缓存的内容一起工作。
我读到我可以使用"loading" : "eager"
来提升第一个查询。所以我在一个新的索引上创建了一个新的映射,命名为myindex_new
{
"mappings": {
"items": {
"dynamic": "strict",
"properties" : {
"title" : { "type": "string" ,
"fielddata": {
"loading" : "eager"}},
"body" : { "type": "string",
"fielddata": {
"loading" : "eager"}},
}},
"user_items": {
"dynamic": "strict",
"_parent": {"type": "items" },
"properties" : {
"user_id" : { "type": "integer" },
"source_id" : { "type": "integer" },
}}}}'
…并按如下方式重新索引了所有内容:
curl -XPOST 'localhost:9200/_reindex' -d '{
"source" : {
"index" : "myindex"
},
"dest" : {
"index" : "myindex_new"
}
}'
问题是我没有得到任何更好的结果。如果我查询带有eager
的新索引,那么第一个查询仍然很慢。我还尝试在子字段上添加eager
,但它仍然很慢。
我一定要做些不同的吗?我在重新索引上做错了什么吗?
提前感谢!
Fielddata用于对这些特定字段进行排序和聚合。它对您的特定查询没有帮助,因为您不使用这些字段进行排序或内部聚合。我会尝试一种不同类型的急切加载,而不是父字段:"loading": "eager_global_ordinals"
。这里有更完整的例子。
父子关系使用全局序数来加速连接。全局序数有两个目的:通过将数字与字符串字段关联来降低内存占用,以及我上面提到的那个。
elasticsearch在父节点和子节点之间使用内存连接来使关系正常工作。对于这些连接,使用全局序数。它们需要被构建和预加载。使用"loading": "eager_global_ordinals"
,它应该预加载全局序数,使搜索更快,因为这些连接已经预加载在内存中。