👐 在数组中的对象内搜索
在我们的书籍中,我们使用了 Attribute Pattern 来在文档中拥有不同的属性。正如我们在 样本文档 中看到的,我们有一个attributes
数组,包含几个对象,每个对象具有相同的结构:
attributes: [
{
key: 'edition',
value: '1st'
},
{
key: 'dimensions',
value: 'Height: 1.111 Inches, Length: 1.111 Inches, Weight: 0.2 Pounds, Width: 1.111 Inches'
},
{
key: 'isbn13',
value: '9780765342508'
},
{
key: 'msrp',
value: 6.99
},
{
key: 'isbn',
value: '0765342502'
},
{
key: 'isbn10',
value: '0765342502'
}
],
我们如何搜索所有售价为9.99的书籍?我们想要在attributes
中有一个对象,其键为msrp
且值为9.99
的书籍。我们可以使用以下方式实现:
db.books.aggregate([
{ $unwind : "$attributes" },
{$match: {"attributes.key": "msrp", "attributes.value": 9.99} },
{$project: {title: 1, attributes: 1}}
]);
在这里,我们为$attributes
数组中的每个对象获取每本书的副本。这将"展开"数组并返回相同文档的多个副本,每个副本具有不同的属性,这些属性对于每个生成的文档都是不同的。
👐 为了更好地理解$unwind
,运行此聚合
db.books.aggregate([
{ $match: {_id: "0395623650"} },
{ $unwind : "$attributes" },
]);
你应该会为原书的每个属性获取一个文档。
但你实际上可以更直接地匹配数组中的文档:
let nineNinetyNine = {$match: {"attributes.key": "msrp", "attributes.value": 9.99}};
let showOnlyTheseFields = {$project: {_id: 0, title: 1, year: 1, totalInventory: 1, available: 1, "attributes": 1}};
db.books.aggregate([
nineNinetyNine,
showOnlyTheseFields,
]);