2014-04-03 27 views
0

以下mongodb查詢未返回文檔。查詢有什麼問題?我想指定$where以匹配數組中的元素

[編輯]上面的問題是我的方案的簡化版本。我正在使用spring數據mongodb存儲庫。我想用@Query註釋來指定查詢。希望$where部分是簡單的比較,而不是一個完整的JavaScript函數。像

@Query (value=" { flag: true, $where: \"this.versions.version == this.defaultVersion \"}", fields = "{'versions' : 1}") 
Foo getDefaultVersion(); 

如果$where是不正確的語法,請建議替代方案。

db.foo.find({ 
    flag: true, 
    $where: "this.versions.version == this.defaultVersion " }, 
    { 'versions' : 1} 
}); 

收藏:

{ 
    flag: true, 
    defaultVersion: "1.0", 
    versions: [ 
     { 
      version: "1.0", 
      tags: ["abc", "def"] 
     }, 
     { 
      version: "1.1", 
      tags: ["abc", "def"] 
     } 
    ] 
} 

我想獲取「版本」從已匹配的版本defaultVersion財產版本排列子文檔。

[EDIT2]我能夠將它縮小使用$ elemMatch

db.foo.find({ 
    flag: true, 
    versions: { $elemMatch : { version: '1.0' } } 
    }, 
    { 'versions' : 1} 
}); 

在上述代替硬編碼'1.0',我想指定文檔的defaultVersion。不知道我該如何實現它?

+0

你的版本是數組,並且this.versions.version會給你未定義的,如果你只想匹配第一個位置,請嘗試使用this.versions [0] .version @Jack – Sumeet

+0

我不知道位置版本上的索引。我希望查詢遍歷所有版本,並將版本與defaultVersion進行匹配。不知道如何寫這個查詢。有什麼建議麼? –

回答

2

在大多數情況下應該避免使用運算符,因爲它既要調用完整的集合掃描,也要避免其他條件可能使用索引選擇。

此外,您正在調用每個結果文檔的JavaScript解釋器,這將比本機代碼慢得多。閱讀手冊頁上的警告,他們在那裏是有原因的

如果可能,請嘗試使用.aggregate()代替這種類型的比較。在你的情況下,它肯定是更好的選擇:

db.foo.aggregate([ 
    { "$match": { "flag": true } }, 
    { "$unwind": "$versions" }, 
    { "$project": { 
     "versions": "$versions" 
     "same": { "$eq": [ "$versions.version", "$defaultVersion" ] } 
    }} 
    { "$match": { "same": true } }, 
    { "$project": { 
     "_id": 0, 
     "versions": 1 
    }} 
]) 

這使您可以首先由「標誌」條件篩選查詢,然後檢查陣列中的每個成員進行比較,如果這兩個領域是相同的。

如果需要,您可以將匹配的數組元素回滾到一個數組,其中有多個匹配項。但我不認爲這是你的要求。

+0

查詢效果很好。我將使用它的spring-data等價物 –

2

試試這個:

db.so.find({ 
    flag: true, 
    $where: function() { 
     var versions = this.versions; 
     for (var i=0; i<versions.length; i++) { 
      if (versions[i].version == this.defaultVersion) return true; 
     } 
    } 
}); 

[編輯] 傑克編輯他的問題,他說,他並不想使用JavaScript函數,而是一個簡單的表達。我不認爲這是可能的。

+0

謝謝。請看我的編輯。 –