MongoDb嵌套数组查询以下关系

3

假设我有一个用户模式:

UserSchema = new Schema({
name:               {
                      first: { type: String, trim: true },
                      last:  { type: String, trim: true }
                    },
username:           { type: String, trim: true, required: true },
email:              { type: String, trim: true, required: true },
hashed_password:    { type: String, trim: true, required: true },
profile_image:      { type: String, trim: true, default: 'default' },
join_date:          { type: Date,     required:true },
userFollows:        [ {
                        status  : { type: String, enum: [
                            'following',
                            'followed_by'
                      ]},
                        added   : { type: Date,   required:true },
                        user    : { type: Schema.ObjectId, ref: 'User'}
                    } ]
})

我需要将一个新用户关注(userFollows)推入这个模式中,但我还需要检查该用户当前是否已经关注了该用户(重复条目),但不确定如何执行此查询。

我正在尝试使用的当前查询是:

User
.findOne(
        {  username: req.user.username },
        { "userFollows.user": { $not: req.body.userID } }
     )
.exec(function (err, currentUser) {

})

但它没有起作用。

我希望在执行查询后避免通过循环遍历currentUser.userFollows数组并手动检查。

我需要推送的最终userFollows对象如下:

{
  _id: ObjectId("53073acd9256e81e4d7b5d8e"),
  status: "followed_by",
  added: ISODate("2014-02-21T11:38:53.828Z"),
  user: ObjectId("51c6ec9fedc1230700000007")
}

只是猜测,但像 findOne { username: req.user.username, "userFollows.user": {$ne: req.body.userID} } 这样的代码应该可以工作。重要的区别在于使用一个对象调用 findOne,而不是两个。 - Andreas Hultgren
我在使用我的查询和上面的查询时都遇到了这个错误: {"code":"InternalError","message":"Cannot read property 'userFollows' of null"}。 - Ross J
2个回答

1

您可以通过以下两种方式之一来进行此更新(使用shell语法):

db.users.update( 
     { "username": req.user.username },
     { $addToSet : { userFollows : { _id: ObjectId("53073acd9256e81e4d7b5d8e"),
                                     status: "followed_by",
                                     added: ISODate("2014-02-21T11:38:53.828Z"),
                                     user: ObjectId("51c6ec9fedc1230700000007")
                                   }
                   }
     }
)

这段代码的意思是,对于当前用户,将此对象添加到userFollows数组中(除非它已经存在)。

另一种方法是:

db.users.update( 
     { "username": req.user.username, "userFollows.user": { $ne: req.body.userID } },
     { $push : { userFollows : { _id: ObjectId("53073acd9256e81e4d7b5d8e"),
                                     status: "followed_by",
                                     added: ISODate("2014-02-21T11:38:53.828Z"),
                                     user: ObjectId("51c6ec9fedc1230700000007")
                                   }
                   }
     }
)

这里说的是:对于这个用户,如果他还没有这个关注者,则$push此对象。

显然,您需要填写适当的字段 - 我只是从您的问题中剪切并粘贴了一些示例值以显示完整格式。


0

请查看关于在更新查询中添加数据到嵌套数组的this

db.collection.update( 
    { username: req.user.username }, 
    { $addToSet: { "userFollows.user": req.user.usernameThatIAdd } }
 );

如果我需要添加状态和添加字段,这个代码还能用吗?最终的userFollows对象看起来像这样:{ status: "followed_by", added: ISODate("2014-02-21T11:38:53.828Z"), user: ObjectId("51c6ec9fedc1230700000007"), _id: ObjectId("53073acd9256e81e4d7b5d8e") } - Ross J
userFollows 不仅仅是用户名。因此,像您建议的 $addToSet 不起作用。 - WiredPrairie
2
而且,你会发现它在语法上实际上不起作用。你会收到一个错误“无法使用字符串字段名'user'附加到数组”。你不能使用“点”语法来使用$addToSet - WiredPrairie
倍增 @WiredPrairie 这样做是行不通的。而且最近我再次问过一次,"谁在给这些完全未经测试和错误的答案点赞?" - Neil Lunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接