Skip to main content

👐 在数组中的对象内搜索

在我们的书籍中,我们使用了 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,
]);