插入测试数据
db.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 } ] } ]);
后面的栗子都会用到这里的测试数据
查询嵌套在数组中的文档
查询 instock 数组中包含 { warehouse: "A", qty: 5 } 的所有文档
> db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
{ "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
嵌套文档内的字段,除了字段名、字段值一样,顺序也得一致,否则不匹配
精确匹配整个文档数组的栗子
> db.inventory.find({instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ]})
{ "_id" : ObjectId("60b6dbbf67b3da7412587548"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
在文档数组中嵌入的字段上指定查询条件
在 instock 数组中,至少有一个文档的 qty 字段值是 ≤20 的
> db.inventory.find( { 'instock.qty': { $lte: 20 } } ) { "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587547"), "item" : "notebook", "instock" : [ { "warehouse" : "C", "qty" : 5 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587548"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587549"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] } { "_id" : ObjectId("60b6dbbf67b3da741258754a"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
访问数组中文档的字段,如果不知道文档的准确索引值,只能按照以下格式
数组字段名.文档字段名
instock.qty
使用数组索引查询嵌入文档中的字段
上面的栗子是直接根据字段名查找
在 instock 数组中,第一个元素包含字段 qty ,且值 ≤20 的文档
> db.inventory.find( { 'instock.0.qty': { $lte: 20 } } ) { "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587547"), "item" : "notebook", "instock" : [ { "warehouse" : "C", "qty" : 5 } ] } { "_id" : ObjectId("60b6dbbf67b3da741258754a"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
在文档数组中的字段指定组合(多个)查询条件
栗子一
找到在 instock 数组中【至少有一个嵌入文档包含 qty > 10,以及至少有一个嵌入文档(但不一定是同一个嵌入文档)包含 qty ≤20 】的文档
> db.inventory.find( { "instock.qty": { $gt: 10, $lte: 20 } } ) { "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587548"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587549"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] } { "_id" : ObjectId("60b6dbbf67b3da741258754a"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
- 不需要在同一个文档同时满足两个条件(当然同一个文档同时满足也可以)
- 只要整个文档数组中,两个条件都至少有一个满足的文档即可
栗子二
找到在 instock 数组中【至少有一个嵌入文档包含 qty = 5,以及至少有一个嵌入文档(但不一定是同一个嵌入文档)包含 warehouse = A 】的文档:
> db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } ) { "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587549"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
在文档数组中单个嵌套文档满足多个查询条件
前言
上面的栗子都是单个嵌套文档或多个嵌套文档满足多个查询条件即可
如果想确保单个嵌套文档必须同时满足多个查询条件呢?
使用 $elemMatch 运算符!(前面讲数组的时候也提到过)
栗子一
找到在 instock 数组【至少有一个包含 qty = 5 和 warehouse = A 的嵌入文档 】的文档
> db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
{ "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
栗子二
找到在 instock 数组【至少有一个包含 qty > 10 且 ≤ 20 的嵌入文档】的文档
> db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } ) { "_id" : ObjectId("60b6dbbf67b3da7412587546"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da7412587548"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] } { "_id" : ObjectId("60b6dbbf67b3da741258754a"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }