我有一个带有子文档的父模式。子文档具有一个包含嵌入对象数组的属性:
子架构
var snippetSchema = new Schema({
snippet: [
{
language: String,
text: String,
_id: false
}
]
});
父架构
var itemSchema = new Schema({
lsin: Number,
identifier: {
isbn13: Number,
},
title: snippetSchema,
});
在Item.find
上返回一个像这样的对象:
[
{
_id: (...),
lsin: 676765,
identifier: {
isbn13: 8797734598763
},
title: {
_id: (...),
snippet: [
{
language: 'se',
text: 'Pippi Långstrump'
}
]
}
}
]
当对象返回给客户端时,我想跳过子文档的一个嵌套级别:
[
{
_id: (...),
lsin: 676765,
identifier: {
isbn13: 8797734598763
},
title: {
language: 'se',
text: 'Pippi Långstrump'
}
}
]
到目前为止,我已经尝试过:
#1使用getter
function getter() {
return this.title.snippet[0];
}
var itemSchema = new Schema({
...
title: { type: snippetSchema, get: getter }
});
但它会创建一个无限循环,从而产生RangeError: Maximum call stack size exceeded
。
#2使用虚拟属性
var itemSchema = new Schema({
..., {
toObject: {
virtuals: true
}
});
itemSchema
.virtual('title2')
.get(function () {
return this.title.snippet[0];
});
这将生成所需的嵌套级别,但是在新属性下,这是不可接受的。据我所知,没有办法用虚拟属性覆盖属性。
问题是:还有其他方法可以获得所需的输出吗?整个应用程序中将有几个对snippetSchema
的引用,并且首选DRY方法。
我是MongoDB和Mongoose的新手。
答案 0 :(得分:1)
您需要在mongodb聚合管道中使用$project
。
在我的数据库中,我有以下内容:
> db.items.find().pretty()
{
"_id" : 123,
"lsin" : 676765,
"identifier" : {
"isbn13" : 8797734598763
},
"title" : {
"_id" : 456,
"snippet" : [
{
"language" : "se",
"text" : "Pippi Långstrump"
}
]
}
}
然后我们只需要创建一个简单的聚合查询:
db.items.aggregate([
{$project: { lsin: 1, identifier: 1, title: { $arrayElemAt: [ '$title.snippet', 0 ] }}}
])
这只是使用$ project(https://docs.mongodb.com/v3.2/reference/operator/aggregation/project/)和$ arrayElemAt(https://docs.mongodb.com/v3.2/reference/operator/aggregation/arrayElemAt/)来投射数组中的第一个项目。如果我们执行该操作,我们将获得以下内容:
{
"_id" : 123,
"lsin" : 676765,
"identifier" : {
"isbn13" : 8797734598763
},
"title" : {
"language" : "se",
"text" : "Pippi Långstrump"
}
}