MongoDB: 使用引用作为键并手动添加值

MongoDB: Using reference as key and manually adding a value

我是 Mongo 数据库的新手,遇到以下问题。 假设我有这样的文档结构,其中用户 Joe Bloggs 观看了一个内容,该内容用 ID 5000 引用:

db.users.insert({
  forname: 'Joe', 
  surname: 'Bloggs', 
  DOB: 12061989, 
  watch: [5000]
});

db.media_content.insert({
  _id: 5000,
  content_name: 'Film XYZ', 
  durations_min: 45, 
  media_type: 'video',
});

我想补充一点,用户 Joe Bloggs 只观看了 35 分钟的 Film XYZ,然而它的时长是 45 分钟。如果我想证明 Joe Bloggs 观看了 Film XYZ 的时间为 35 分钟,我将如何添加它以及查询会是什么样子。

--- 更新 ---

我没有进行更新,而是重新编码以便尝试:

db.users.insert({
  forname: 'Tom',
  surname: 'Smith',
  DOB: 22081989,
  watch: [{
            media_id: 6000,
            stream_min: 35
            }]
});

db.media_content.insert({
  _id: 6000,
  content_name: 'Film XYZ', 
  durations_min: 45, 
  media_type: 'video',
});

var minutes_watched = db.users.find(
{
    "forname": "Tom", 
    "surname": "Smith", 
    "DOB": 22081989, 
    "watch.media_id": 6000
}, 
{ 
    "watch": { 
        "$elemMatch": { "media_id": 6000 } 
    } 
}).watch[0].minutes_watched;

我以为我成功了,但我仍然收到消息:

TypeError: Cannot read property 'watch' of null.

我做错了什么?

您可以重组您的文档架构,使 watch 数组将转换为同时具有参考 ID 和观看分钟数属性的嵌入式文档,而不是仅具有 ID 值的数组.像这样 $push 更新应该做的事情:

db.users.update({
        "forname": "Joe", 
        "surname": "Bloggs", 
        "DOB": 12061989, 
        "watch": 5000
    },
    {
        "$push": {
            "watch": {
                "media_id": 5000,
                "minutes_watched": 35
            }
        }
    }
);

以上更新了用户 "Joe" 的用户文档,以在具有上述属性的 watch 数组中添加嵌入文档。为了整理一下,您可以 $pull 另一个 watch 值为 5000

的数组元素
db.users.update({
        "forname": "Joe", 
        "surname": "Bloggs", 
        "DOB": 12061989, 
        "watch": 5000
    },
    {
        "$pull": { "watch": 5000 }
    }
);

既然你现在有实际的观看时长和媒体 ID 详细信息都嵌入在用户文档中,你可以查询给定媒体 ID 的两个集合以获取观看分钟数(使用 $elemMatch watch 数组以投影该字段)和电影详细信息如下:

var minutes_watched = db.users.findOne(
    {
        "forname": "Joe", 
        "surname": "Bloggs", 
        "DOB": 12061989, 
        "watch.media_id": 5000
    }, 
    { 
        "watch": { 
            "$elemMatch": { "media_id": 5000 } 
        } 
    }).watch[0].minutes_watched;

var movie = db.media_content.findOne({"_id": 5000});

编辑

如果用户再观看 2 部电影,一部 ID 为 4567 的电影在总共 80 分钟中观看了 20 分钟,另一部 ID 为 1234 的电影观看了 58 分钟,您只需将这些详细信息推送到 watch 数组使用 $addToSet with $each 像这样:

db.users.update({
        "forname": "Joe", 
        "surname": "Bloggs", 
        "DOB": 12061989
    },
    {
        "$addToSet": {
            "watch": { 
                $each: [ 
                    { "media_id": 4567, "minutes_watched": 20 }, 
                    { "media_id": 1234, "minutes_watched": 58 }                 
                ] 
            }
        }
    }
);

对用户 "Joe" db.users.findOne({"forname": "Joe"}) 的查询将产生更新后的文档:

/* 1 */
{
    "_id" : ObjectId("553d143ac96712b936005274"),
    "forname" : "Joe",
    "surname" : "Bloggs",
    "DOB" : 12061989,
    "watch" : [ 
        {
            "media_id" : 5000,
            "minutes_watched" : 35
        }, 
        {
            "media_id" : 4567,
            "minutes_watched" : 20
        }, 
        {
            "media_id" : 1234,
            "minutes_watched" : 58
        }
    ]
}