2012-02-12 40 views
7

最近我想篩選出包含在MongoDB中某個關鍵字陣列記錄,例如記錄:我有五個記錄包含關鍵字數組:MongoDB的熒光燈,如何查找包含特定關鍵字陣列

{a:[1,2]} 
{a:[1,3,8]} 
{a:[1,2,5]} 
{a:[3,5,1]} 
{a:[4,5]} 

如果我輸入搜索數組[1,2,3,5],然後我想:

{a:[1,2]} 
{a:[1,2,5]} 
{a:[3,5,1]} 

他們每個人是[1,2,3,5]子陣列。

有什麼想法?

請不要使用where子句(當possbile)時。謝謝!

+0

你喜歡需要在js中爲此編寫一個自定義過濾器,然後將其用作查詢的一部分。 http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-JavascriptExpressionsand%7B%7B%24where%7D%7D – Travis 2012-02-12 16:31:18

回答

8

它在mongodb中很容易做到,但更難的部分是爲查詢準備數據。讓我來解釋一下,在奧德

簡單的零件

您可以使用$in找到數組中的匹配元素。讓我們試着

db.coll.find({a:{$in:[1,2,3,5]}) 

,其結果是

{ "_id" : ObjectId("4f37c41739ed13aa728e9efb"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f37c42439ed13aa728e9efc"), "a" : [ 1, 3, 8 ] } 
{ "_id" : ObjectId("4f37c42c39ed13aa728e9efd"), "a" : [ 1, 2, 5 ] } 
{ "_id" : ObjectId("4f37c43439ed13aa728e9efe"), "a" : [ 3, 5, 1 ] } 
{ "_id" : ObjectId("4f37c43e39ed13aa728e9eff"), "a" : [ 4, 5 ] } 

喔,它不是我們所期望的結果。是的,因爲如果找到任何匹配元素(不一定全部),則返回一個項目。

所以我們可以通過將確切的數組元素傳遞給$ in來解決這個問題,例如,如果我們想找到匹配這些確切數組的項{a:[1,2]} {a:[1,2,5 ]}和{一:[4,5,6]}

db.coll.find({a:{$in:[[1,2],[1,2,5],[4,5,6]]}}) 

你會得到

{ "_id" : ObjectId("4f37c41739ed13aa728e9efb"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f37c42c39ed13aa728e9efd"), "a" : [ 1, 2, 5 ] } 

這就是所有

最難的部分

真正最難的部分是形成你的輸入數組[1,2,3,5]的所有可能的組合。您需要找到一種方法來獲取源數組的所有組合(從您的客戶端)並將其傳遞給$ in。

例如,這JS method會給你所有給定陣列的

var combine = function(a) { 
    var fn = function(n, src, got, all) { 
    if (n == 0) { 
     if (got.length > 0) { 
     all[all.length] = got; 
     } 
     return; 
    } 
    for (var j = 0; j < src.length; j++) { 
     fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all); 
    } 
    return; 
    } 
    var all = []; 
    for (var i=0; i < a.length; i++) { 
    fn(i, a, [], all); 
    } 
    all.push(a); 
    return all; 
} 

>> arr= combine([1,2,3,5]) 

會給你

[ 
    [ 
     1 
    ], 
    [ 
     2 
    ], 
    [ 
     3 
    ], 
    [ 
     5 
    ], 
    [ 
     1, 
     2 
    ], 
    [ 
     1, 
     3 
    ], 
    [ 
     1, 
     5 
    ], 
    [ 
     2, 
     3 
    ], 
    [ 
     2, 
     5 
    ], 
    [ 
     3, 
     5 
    ], 
    [ 
     1, 
     2, 
     3 
    ], 
    [ 
     1, 
     2, 
     5 
    ], 
    [ 
     1, 
     3, 
     5 
    ], 
    [ 
     2, 
     3, 
     5 
    ], 
    [ 
     1, 
     2, 
     3, 
     5 
    ] 
] 

組合,你可以通過這個arr至$在找到所有macthing元素

 db.coll.find({a:{$in:arr}}) 

會給你

{ "_id" : ObjectId("4f37c41739ed13aa728e9efb"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f37c42c39ed13aa728e9efd"), "a" : [ 1, 2, 5 ] } 

等等!,它仍然沒有返回其餘兩個可能的項目。

因爲看看arr,它只能找到組合。它返回[1,3,5]但文檔中的數據是[3,5,1]。所以它清楚$in檢查項目按給定的順序(奇怪!)。

所以,現在你明白它比較mongodb查詢真的很難!您可以更改上述JS組合的前代碼,以查找每個組合的可能排列並將其傳遞給mongodb $in。這就是訣竅。

由於您沒有提及任何語言選擇,所以很難推薦任何置換代碼。但是你可以在Stackoverflow或Google上找到很多不同的方法。

0

如果我的理解,要返回了其財產a所有值在查找數組參數對象。

依照與特拉維斯的意見建議,你必須遵循以下步驟:

  1. 定義一個JS函數來實現你的願望(因爲有這樣做MongoDB中沒有原生的方式);
  2. 將該功能保存在服務器上;
  3. 使用$where中的功能。

如果定義函數只用來爲特定屬性(a,在這種情況下),你可能要跳過步驟2。然而,由於它可以爲其他文件的其他性質的有用的功能,我定義了一個更通用的功能,必須保存在服務器上才能使用AFAIK(我也是Mongo的新手)。

下面有我在蒙戈外殼測試:

<--! language: lang-js --> 

// step 1: defining the function for your specific search 
only = function(property, values) { 
    for(var i in property) if (values.indexOf(property[i]) < 0) return false 
    return true 
} 

// step 2: saving it on the server 
db.system.js.save({ _id : 'only', value : only }) 

// step 3: using the function with $where 
db.coll.find({$where: "only(this.a, [1,2,3,5])"}) 

與您提供有關這個問題的5個對象,你將獲得:

{ "_id" : ObjectId("4f3838f85594f902212eb532"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f3839075594f902212eb534"), "a" : [ 1, 2, 5 ] } 
{ "_id" : ObjectId("4f38390e5594f902212eb535"), "a" : [ 3, 5, 1 ] } 

缺點是性能。 See more.

相關問題