2016-04-06 41 views
4

我想搜索數組中的字段,並且想知道數組中的字段的索引是否可以找到它? 例如:通過相對數組元素位置查找文檔

doc1: {id:123, hobby:['chess','cards','dance']} 
doc2: {id:123, hobby:['cards','dance','chess']} 

我只想搜索具有 chesscards但只有具有chesscard前一個文件。所以如果是doc1

回答

3

您可以用$where運營商做到這一點,與$all操作偶聯,以保持其合理高性能:

db.test.find({ 
    // Find all the docs where hobby contains both 'cards' and 'chess' 
    hobby: {$all: ['cards', 'chess']}, 
    // Of those, run this $where query that evaluates the indexes of the matched elements 
    $where: "this.hobby.indexOf('cards') > this.hobby.indexOf('chess')" 
}) 

hobby添加一個索引以獲得最佳性能。

0

對於你實際上有$match階段使用.aggregate()爲「查詢」,以可能的匹配縮小到包含$all數組中的元素文檔的最佳性能,並$redact從其餘結果進行過濾:

db.test.aggregate([ 
    { "$match": { "hobby": { "$all": [ "chess", "cards" ] } } }, 
    { "$redact": { 
    "$cond": { 
     "if": { 
     "$eq": [ 
      { "$filter": { 
       "input": "$hobby", 
       "as": "hobby", 
       "cond": { 
       "$or": [ 
        { "$eq": [ "$$hobby", "chess" ] }, 
        { "$eq": [ "$$hobby", "cards" ] } 
       ] 
       } 
      }}, 
      ["chess","cards"] 
     ] 
     }, 
     "then": "$$KEEP", 
     "else": "$$PRUNE" 
    }  
    }} 
]) 

的作品是因爲$filter只能返回匹配這裏給出的條件的元素,並將其返回「以相同的順序」它們被存儲在原始文檔中的原因。

一旦「過濾」下,該陣列然後應是完全匹配用於內容["chess","cards"]如果確實原始數組中的那些元件都以該順序。

請注意,雖然它可能「看起來」更簡單,但您不能使用"set operators"來測試此操作,因爲「sets」實際上並未被認爲是有序的。

所以你需要維護順序的東西,而$filter真的是唯一能夠以有效的方式對數組內容做到這一點的東西。所以這個解決方案實際上僅限於需要一個MongoDB 3.2或更高版本才能實際工作。

對於較老的版本中,使用$where對的數組元素作爲附加濾波器使用$all施加.indexOf()測試看到answer from JohnnyHK

但是,如果您的MongoDB 3.2具有可用的運算符,那麼可用於聚合框架的本機編碼操作運行速度比$where的JavaScript評估要快得多,應優先使用。

相關問題