2012-11-25 42 views
0

我们使用两种类型的弹性搜索(ES)文档:项目和插槽,其中项目是插槽文档的父项。 我们定义使用以下命令索引:查询elasitsearch父级子文档

curl -XPOST 'localhost:9200/items' -d @itemsdef.json 

其中itemsdef.json具有以下定义

{ 
"mappings" : { 
    "item" : { 
     "properties" : { 
      "id" : {"type" : "long" }, 
      "name" : { 
       "type" : "string", 
       "_analyzer" : "textIndexAnalyzer" 
      }, 
      "location" : {"type" : "geo_point" }, 
     } 
    } 
}, 
"settings" : { 
    "analysis" : { 
     "analyzer" : { 

       "activityIndexAnalyzer" : { 
        "alias" : ["activityQueryAnalyzer"], 
        "type" : "custom", 
        "tokenizer" : "whitespace", 
        "filter" : ["trim", "lowercase", "asciifolding", "spanish_stop", "spanish_synonym"] 
       }, 
       "textIndexAnalyzer" : { 
        "type" : "custom", 
        "tokenizer" : "whitespace", 
        "filter" : ["word_delimiter_impl", "trim", "lowercase", "asciifolding", "spanish_stop", "spanish_synonym"] 
       }, 
       "textQueryAnalyzer" : { 
        "type" : "custom", 
        "tokenizer" : "whitespace", 
        "filter" : ["trim", "lowercase", "asciifolding", "spanish_stop"] 
       }  
     }, 
     "filter" : {   
       "spanish_stop" : { 
        "type" : "stop", 
        "ignore_case" : true, 
        "enable_position_increments" : true, 
        "stopwords_path" : "analysis/spanish-stopwords.txt" 
       }, 
       "spanish_synonym" : { 
        "type" : "synonym", 
        "synonyms_path" : "analysis/spanish-synonyms.txt" 
       }, 
       "word_delimiter_impl" : { 
        "type" : "word_delimiter", 
        "generate_word_parts" : true, 
        "generate_number_parts" : true, 
        "catenate_words" : true, 
        "catenate_numbers" : true, 
        "split_on_case_change" : false     
       }    
     } 
    } 
} 
} 

然后我们使用以下命令添加子文档定义:

curl -XPOST 'localhost:9200/items/slot/_mapping' -d @slotsdef.json 

在哪里slotsdef.json定义如下:

{ 
"slot" : { 
    "_parent" : {"type" : "item"}, 
    "_routing" : { 
     "required" : true, 
     "path" : "parent_id" 
    }, 
    "properties": { 
     "id" : { "type" : "long" }, 
     "parent_id" : { "type" : "long" }, 
     "activity" : { 
      "type" : "string", 
      "_analyzer" : "activityIndexAnalyzer" 
     }, 
     "day" : { "type" : "integer" }, 
     "start" : { "type" : "integer" }, 
     "end" : { "type" : "integer" } 
    } 
} 
} 

最后,我们用下面的命令执行批量指数:

curl -XPOST 'localhost:9200/items/_bulk' --data-binary @testbulk.json 

凡testbulk.json持有以下数据:

{"index":{"_type": "item", "_id":35}} 
{"location":[40.4,-3.6],"id":35,"name":"A Name"} 
{"index":{"_type":"slot","_id":126,"_parent":35}} 
{"id":126,"start":1330,"day":1,"end":1730,"activity":"An Activity","parent_id":35} 

我试图让下面的查询:搜索对于在特定日期以及某些开始和结束范围内具有子(位置)的位置的特定距离内的所有项目。

满足条件的更多插槽的项目应该得分更高。

我试着从现有的样本开始,但文档非常稀缺,很难前进。

线索?

回答

0

我不认为有一种方法可以编写一个高效的查询,可以做到这样的事情,而无需将位置移至槽位。你可以做这样的事情,但对于有些数据相当低效:

{ 
    "query": { 
     "top_children" : { 
      "type": "blog_tag", 
      "query" : { 
       "constant_score" : { 
        "query" : { 
         ... your query for children goes here ... 
        } 
       }    
      }, 
      "score" : "sum", 
      "factor" : 5, 
      "incremental_factor" : 2 
     } 
    }, 
    "filter": { 
     "geo_distance" : { 
      "distance" : "200km", 
       "location" : { 
        "lat" : 40, 
        "lon" : -70 
       } 
      } 
     } 
    } 
} 

基本上,这个查询做是这样的,它需要你的范围查询或筛选的儿童和任何你需要的其他条件和包装它进入constant_score查询,以确保所有的孩子都有1.0的分数。 top_children查询收集所有这些孩子,并将他们的分数累积给父母。然后过滤掉父母太远的父母。

+0

如何应用某种程度的非规范化?可能会将所有可搜索的父属性移动到子项,并将父项作为结构来分组子项。嵌套文档会更好吗? –

+0

是的,正如我在回答开始时提到的,将位置移动到插槽可能会有所帮助。我会建议做一些测试,看看你是否得到合理的性能,然后在非规范化后重复这些测试。 – imotov