MongoDB 陣列使用大全

因為這次內容比較多,就減少文字的描述了,直接上乾貨(X),直接上範例與結果。


測試資料

1
2
3
db.arraycollection.insert({fruits:['apple', 'guava', 'orange', 'watermelon', 'pitaya', 'durian']})
db.arraycollection.insertMany([{field:1},{field:2},{field:3},{field:4},{field:5}])
db.arraycollection.insert({num:[1,2,3,4,5]})

查詢

1
2
3
4
5
6
> db.arraycollection.find({fruits: [ "apple", "guava", "orange", "watermelon", "pitaya" ] } )
>

> db.arraycollection.find({fruits: [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] } )

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

$all

給予一陣列進行查詢,都要符合才找得到

1
2
3
4
5
6
7
8
9
10
11
12
13
> db.arraycollection.find({fruits:{$all:['apple']}})

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

> db.arraycollection.find({fruits:{$all:['guava','apple']}})

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

> db.arraycollection.find({fruits:{$all:['Apple']}})
>

> db.arraycollection.find({fruits:{$all:['apple', 'grapes']}})
>

$elemMatch

給予一陣列進行查詢,其中一項符合就算,還能夠加上更多運算符進行操作。

1
2
3
4
5
6
7
8
> db.arraycollection.find({fruits:{$elemMatch:{$eq:'apple'}}})

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

> db.arraycollection.find({fruits:{$elemMatch:{$in:['apple','guava']}}})

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

$size

計算陣列元素的數量

1
2
3
4
5
> db.arraycollection.find({fruits:{$size:5}})

> db.arraycollection.find({fruits:{$size:6}})
{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }
>

同場加應,取得欄位的陣列長度

不太確定為什麼網路上很難找到這個使用方式,多半都是進行比較的,例如大於小於等於者種,如上面的例子。

如果要取得陣列數量:

1
db.arraycollection.aggregate([ { $project: { count: { $size: '$fruits' } } } ]])

$in

比較對象:陣列
比較值:陣列
給予一個陣列,只要有符合陣列內的任意一個值都算

1
2
3
4
5
6
7
> db.arraycollection.find({fruits:{$in:['apple']}})

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

> db.arraycollection.find({fruits:{$in:['apple','zzz']}})

{ "_id" : ObjectId("619e633a370002a1c5b7d94c"), "fruits" : [ "apple", "guava", "orange", "watermelon", "pitaya", "durian" ] }

看完查詢,也可以用索引值來取得陣列內容,但要特別注意 MongoDB 支援的版本

  • Sample Data
1
2
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5 ] }

$slice

  • format: db.collection.find({},{num: {$slice: z} })
    z 為數字,從起點開始取幾個值,-1 則是從倒數最後一個開始
1
2
3
4
5
6
7
8
9
10
11
12
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:1}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:99}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:-1}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 5 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:-2}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 4, 5 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:-99}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5 ] }
>
  • format: db.collection.find({},{num: {$slice: [x, y]} })
    x 為數字,略過元素數量
    y 為數字,開始取幾個值
1
2
3
4
5
6
7
8
> db.tc.find({num: {$exists:true}} ,{num:{$slice:[0,1]}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:[0,2]}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:[1,2]}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 2, 3 ] }
> db.tc.find({num: {$exists:true}} ,{num:{$slice:[1,99]}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 2, 3, 4, 5 ] }

Update

$push

從最後一個元素開始,寫入陣列

如果該 field 不存在,則會直接新增,例如下面的 num 欄位不存在,會直接在該文件新增此欄位。

1
2
3
4
5
> db.tc.update({num: {$exists:true}} ,{$push:{num:6}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({num: {$exists:true}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5, 6 ] }

寫入多個,結果不符合預期

1
2
3
4
5
> db.tc.update({num: {$exists:true}} ,{$push:{num:[7,8]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({num: {$exists:true}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5, 6, [ 7, 8 ] ] }

寫入多個,需要額外配上 $each operator

1
2
3
4
5
6
> db.tc.update({num: {$exists:true}} ,{$push:{num:{$each:[9,10]}} })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({num: {$exists:true}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5, 6, [ 7, 8 ], 9, 10 ] }
>

$addToSet

使用上基本和 $push 差不多,但是呢~ $addToSet 無法寫入重複的值
例如以下範例,假設 int1 這個欄位已經有 2 這個值,則這個語法執行在多次,也不會有修改,所以可以看到 WriteResult 只有發現 match 但沒有修改。

1
2
> db.tc.update({_id:ObjectId("619f58d4a447b323d0af92e5")}, {$addToSet: {int1:2}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

$pop

從頭或從尾移除特定數量的值,要記得預設是從最末端開始,因此

  • -1: 從第一個移除一個值
  • 1 : 從最後一個移除一個值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Given
> db.tc.find({num: {$exists:true}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5, 6, [ 7, 8 ], 9, 10 ] }

// 1
> db.tc.update({num: {$exists:true}} ,{ $pop: {num:1} })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({num: {$exists:true}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 1, 2, 3, 4, 5, 6, [ 7, 8 ], 9 ] }

// -1
> db.tc.update({num: {$exists:true}} ,{ $pop: {num:-1} })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({num: {$exists:true}})
{ "_id" : ObjectId("619f463da447b323d0af92e4"), "num" : [ 2, 3, 4, 5, 6, [ 7, 8 ], 9 ] }

$pull

pull 的功能是移除陣列內特定的(符合條件)元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Given
> db.tc.find({_id:ObjectId("619f58d4a447b323d0af92e5")})
{ "_id" : ObjectId("619f58d4a447b323d0af92e5"), "arr1" : [ 1, 2, 3, 4, 5 ], "arr2" : [ 101, 102, 103, 104, 105 ] }

// pull arr:1
> db.tc.update({_id:ObjectId("619f58d4a447b323d0af92e5")}, {$pull: {arr1: 1} })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({_id:ObjectId("619f58d4a447b323d0af92e5")})
{ "_id" : ObjectId("619f58d4a447b323d0af92e5"), "arr1" : [ 2, 3, 4, 5 ], "arr2" : [ 101, 102, 103, 104, 105 ] }

// pull arr1:[2, 3]
> db.tc.update({_id:ObjectId("619f58d4a447b323d0af92e5")}, {$pull: {arr1: {$in: [2,3]}} })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({_id:ObjectId("619f58d4a447b323d0af92e5")})
{ "_id" : ObjectId("619f58d4a447b323d0af92e5"), "arr1" : [ 4, 5 ], "arr2" : [ 101, 102, 103, 104, 105 ] }

// pull arr2: 104
> db.tc.update({_id:ObjectId("619f58d4a447b323d0af92e5")}, {$pull: {arr2: 104 }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.tc.find({_id:ObjectId("619f58d4a447b323d0af92e5")})
{ "_id" : ObjectId("619f58d4a447b323d0af92e5"), "arr1" : [ 4, 5 ], "arr2" : [ 101, 102, 103, 105 ] }
  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。