我有以下架构:
//define suberSchema
var suberSchema = new Schema({
_id: {
type: Schema.Types.ObjectId,
required: true
},
constraints: [constraintSchema]
});
//define spaceInfoSchema
var spaceInfoSchema = new Schema({
spaceName: String,
subers: [suberSchema],
_id: {
type: Schema.Types.ObjectId,
required: true
}
});
我想操纵/获取子文件,但是当我使用下面的代码时,它只是操作parentdocs。
spaceInfoModel.find({"_id": spaceId,"subers._id": userId}, "subers", callback);
spaceInfoModel.remove({"_id": spaceId,"subers._id": userId}, callback);
提前致谢。
答案 0 :(得分:1)
find()
将始终从调用它的集合中返回文档。在您的示例中spaceInfoModel
。查询:spaceInfoModel.find({"_id": spaceId,"subers._id": userId}, "subers", callback);
正在检查spaceInfoModel
集合中与spaceId
的ID匹配的文档,并且还有一个ID为{{1}的子文档}。如果找到任何匹配的文档,它们将作为数组返回给回调函数。
此时,您可以使用辅助函数id()
来检索子文档:
userId
然而,返回所有子文档会产生令人遗憾的副作用,因此您可以将其修剪为1。一种更有效的方法是让Mongo在返回父文档之前削减子doc数组。 $elemMatch
投影运算符可用于执行此操作。
// Using findOne but you could easily match this with findById as well
spaceInfoModel.findOne({"_id": spaceId,"subers._id": userId}, 'subers').exec().then(function(spaceInfo) {
// spaceInfo.subers is the entire sub-doc array
return spaceInfo.subers.id(userId);
}).then(function(suber) {
// do something with the suber
}).then(null, function(err) { ... });
除此之外,您还可以探索使用聚合管道来展开文档子文档,但我不相信使用spaceInfoModel.findById(spaceId).select({subers: {$elemMatch: {_id: userId}}}).exec().then(function(spaceInfo) {
// spaceInfo.subers is an array of only the matching sub-doc
return spaceInfo.subers.id(userId);
}).then(function(suber) {
// do something with the suber
}).then(null, function(err) { ... });
会有很多好处。
要删除子文档,可以采用类似的方式。第一种方法需要检索整个数组,然后使用pull()
在本地修改它,然后再将其保存回MonogoDB。
elemMatch()
同样,这可以直接在MongoDB服务器上更有效地完成。
spaceInfoModel.findOne({"_id": spaceId,"subers._id": userId}, 'subers').exec().then(function(spaceInfo) {
// spaceInfo.subers is the entire sub-doc array
// remove the matching ID
spaceInfo.subers.pull({_id: userId});
// Commit to mongoDB
return spaceInfo.save();
}).then(function() {
...
}).then(null, function(err) { ... });
注意: spaceInfoModel.findByIdAndUpdate(spaceId, {$pull: {subers: {_id: userId}}}).select({subers: {$elemMatch: {_id: userId}}}).exec().then(function(spaceInfo) {
// spaceInfo.subers is an array of only the matching sub-doc
// the original doc is returned with the removed sub-doc on success
return spaceInfo.subers.id(userId);
}).then(function(suber) {
// do something with the suber
}).then(null, function(err) { ... });
仅用于返回已删除的子文档。如果您不在乎,可以将其简化为:
$elemMatch
答案 1 :(得分:0)
你必须这样做
spaceInfoModel.aggregate({$match
{
"_id": spaceId,
}},{$unwind:'$subers"}, {$match:{
"subers._id": userId
}}, "subers", callback);
你得到这样的结果
[{_id: '****',subers: {_id: '',constraints: [some data]}}]
删除
spaceInfoModel.update(
{
"_id": spaceId,
"subers._id": userId
},{$pull:{subers:{_id:userId}}},callback)