mongodb 对象数组查询

本文总结了如何在 mongoDB 中对对象数组(数组中包含的元素类型是对象)进行查询。

集合数据

假设有如下文档,集合名为 ventory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
db.collection('inventory').insertMany([
{
item: 'journal',
instock: [
{ warehouse: 'A', qty: 5 },
{ warehouse: 'C', qty: 15 }
]
},
{
item: 'notebook',
instock: [{ warehouse: 'C', qty: 5 }]
},
{
item: 'paper',
instock: [
{ warehouse: 'A', qty: 60 },
{ warehouse: 'B', qty: 15 }
]
},
{
item: 'planner',
instock: [
{ warehouse: 'A', qty: 40 },
{ warehouse: 'B', qty: 5 }
]
},
{
item: 'postcard',
instock: [
{ warehouse: 'B', qty: 15 },
{ warehouse: 'C', qty: 35 }
]
}
]);

在集合中精确匹配一个完整的嵌套文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 仅当 instock 中有元素为 { warehouse: 'A', qty: 5 } 时才返回
db.collection('inventory').find({
instock: { warehouse: 'A', qty: 5 }
})

// 结果
// 1
{
"_id": ObjectId("6245b2876c0b0000c00070a8"),
"item": "journal",
"instock": [
{
"warehouse": "A",
"qty": 5
},
{
"warehouse": "C",
"qty": 15
}
]
}

该查询同匹配数组中的某个基本元素一样的原理。

对数组中文档的某个字段按条件匹配

按数组中对象的某个字段匹配

1
2
3
4
// 只要数组中有一个元素的 qty 满足条件就返回值
db.collection('inventory').find({
'instock.qty': { $lte: 20 }
})

按数组中特定位置对象的某个字段匹配

数组中元素的索引从 0 开始。

1
2
3
4
// 当 instock 数组中第 1 个元素的 qty 满足条件时返回
db.collection('inventory').find({
'instock.0.qty': { $lte: 20 }
});

对数组中的文档进行多条件匹配

数组中多个元素共同满足一组条件

下列查询中,当满足以下情况之一时,会有返回值:

  1. instock 中的一个元素有字段 qty 且满足 $gt: 15,另一个元素也有字段 qty 且满足$lte: 20
  2. instock 中的一个元素有字段 qty 且同时满足匹配条件
1
2
3
db.collection('inventory').find({
'instock.qty': { $gt: 10, $lte: 20 }
});

下列查询中,当满足以下情况之一时,会有返回值:

  1. instock 中的一个元素有字段 qty 且值为 5,另一个元素有字段 warehouse 且值为 A
  2. instock 中的一个元素有字段 qty 且值为 5,该元素同时有字段 warehouse 且值为 A
1
2
3
4
db.collection('inventory').find({
'instock.qty': 5,
'instock.warehouse': 'A'
})

这种匹配机制概括为:

只要条件被数组中的元素共同满足后,就会返回。就像工作中分配任务一样,只要任务被完成,具体的完成人有几个可以不用关心。

数组中任一个元素同时满足一组条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
db.collection('inventory').find({
instock: { $elemMatch: { qty: 5, warehouse: 'A' } }
})

// 结果
// 1
{
"_id": ObjectId("6245b2876c0b0000c00070a8"),
"item": "journal",
"instock": [
{
"warehouse": "A",
"qty": 5
},
{
"warehouse": "C",
"qty": 15
}
]
}

参考

  1. Query an Array of Embedded Documents