2014-01-22 114 views
2

我有兩個文檔類型,在一個父子關係:麻煩與has_parent查詢function_score

"myParent" : { 
    "properties" : { 
    "weight" : { 
     "type" : "double" 
    } 
    } 
} 

"myChild" : { 
    "_parent" : { 
    "type" : "myParent" 
    }, 
    "_routing" : { 
    "required" : true 
    } 
} 

weight字段是要被用於定製的得分/排序。該查詢直接對母文件按預期工作:

{ 
    "query" : { 
    "function_score" : { 
     "script_score" : { 
     "script" : "_score * doc['weight'].value" 
     }     
    }                  
    }  
} 

然而,試圖用一個has_parent查詢子文檔做類似的進球時,我得到一個錯誤:

{ 
    "query" : { 
    "has_parent" : { 
     "query" : { 
     "function_score" : {              
      "script_score" : { 
      "script" : "_score * doc['weight'].value" 
      } 
     } 
     }, 
     "parent_type" : "myParent", 
     "score_type" : "score" 
    } 
    } 
} 

的錯誤是:

QueryPhaseExecutionException[[myIndex][3]: query[filtered(ParentQuery[myParent](filtered(function score (ConstantScore(:),function=script[_score * doc['weight'].value], params [null]))->cache(_type:myParent)))->cache(_type:myChild)],from[0],size[10]: Query Failed [failed to execute context rewrite]]; nested: ElasticSearchIllegalArgumentException[No field found for [weight] in mapping with types [myChild]];

好像而不是應用打分函數給家長,那麼它的結果傳遞給孩子,ES嘗試應用評分向孩子發生作用,導致錯誤。

如果我沒有使用score作爲score_type,則不會發生錯誤,雖然結果得分然後全部爲1.0,如記錄。

我在這裏錯過了什麼?我如何通過基於父字段的自定義評分來查詢這些子文檔?

+0

賞金? :) – DrTech

+0

@DrTech耐心,伊阿古,耐心;) –

+0

:D /我耐心地等待 – DrTech

回答

6

此我想說的是一個錯誤:它使用的是myChild映射,默認情況下,即使您在has_parent查詢。但我不確定這個bug是多麼容易修復。正常。

然而,你可以解決它通過包括type名在滿場的名字:

curl -XGET "http://localhost:9200/t/myChild/_search" -d' 
{ 
    "query": { 
    "has_parent": { 
     "query": { 
     "function_score": { 
      "script_score": { 
      "script": "_score * doc[\"myParent.weight\"].value" 
      } 
     } 
     }, 
     "parent_type": "myParent", 
     "score_type": "score" 
    } 
    } 
}' 

我開了一個問題,看看我們是否能得到這個固定#4914

+0

謝謝,這就是訣竅!我認爲從腳本的子上下文中引用父代不會增加成本,因爲它們將始終處於同一個分片中? –

+0

正確 - 無額外費用。 – DrTech

+0

奇怪的是,Martijn v格羅寧根從[ES討論主題](https://groups.google.com/forum/#)鏈接到[gist](https://gist.github.com/martijnvg/8639841) !msg/elasticsearch/w7zgncPYMVY/K3qRlpd7TQ0J)無法重現問題。我很難看出有什麼不同。無論如何,再次感謝。 –

2

我認爲問題在於您試圖根據parent文檔中的字段對child文檔進行評分,並且功能評分應該是相反的。

爲了解決這個問題,我的想法是將父/子關係和分數存儲在子文檔中。然後,您將篩選子文檔並根據子文檔中的weight對它們打分。

一個例子:

"myParent" : { 
    "properties" : { 
     "name" : { 
      "type" : "string" 
     } 
    } 
} 

"myChild" : { 
    "_parent" : { 
     "type" : "myParent" 
    }, 
    "_routing" : { 
     "required" : true 
    }, 
    "properties": { 
     "weight" : { 
      "type" : "double" 
     } 
    } 
} 

現在你可以使用has_parent過濾器來選擇具有一定parent,然後將所有child文件使用function score得分他們:

{ 
    "query": { 
     "filtered": { 
      "query": { 
       "function_score" : { 
        "script_score" : { 
         "script" : "_score * doc['weight'].value" 
        } 
       } 
      }, 
      "filter": { 
       "has_parent": { 
        "parent_type": "myParent", 
        "query": { 
         "term": { 
          "name": "something" 
         } 
        } 
       } 
      } 
     } 
    } 
} 

所以如果parent文件是博客文章和child評論,那麼你可以過濾所有帖子,並根據weight評分評論。我懷疑,基於parents得分childs可能,雖然我可能是錯的:)

免責聲明:1後溢出堆棧...

+0

「你正在試圖根據'parent'文件中的一個字段對'child'文件進行評分你是說設計錯了,或解釋錯誤?這個錯誤對我來說沒有意義,因爲'script_score'在'has_parent'查詢中,所以我希望它能在'parent'文件上運行。 –

+0

'has_parent'查詢返回具有某個父級的'child'文檔。因此,在映射類型[myChild]時發現錯誤'沒有爲[weight]找到字段「,這基本上是說'script_score'函數試圖訪問'weight'字段,該字段僅存在於'myParent'中。所以是的,你需要改變設計。 – truemped

+0

就像我說過的,'script_score'是* has_parent'中的*,所以我期望'doc'在腳本中引用'myParent'。 –