2012-11-25 41 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