2

给定 MongoDB 中的以下用户对象,最快的搜索方式是relation.$.status == 'friends'什么?

需要找到一种方法来获取包含值为 的对象finduser集合数据(请参阅下面的伪查询)。relation"friends"

此特定集合的键已设置为 uid,因此假设下面的“用户数据”部分可能不会更改。

用户数据:

{
    "_id": ObjectId('1a1a1a1a111a1a11a1a1a1a'),
    "name": "Tester",
    "relation": {
        "2b2b2b2b2b2b2b2b2b2b2b": {
            "status": 'friends',
            "status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
            // etc...
        },
        "3c3c3c3c3c3c3c3c3c3c3c": {
            "status": 'engaged',
            "status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
            // etc...
        }
    }
}

询问:

var query = {
    // pseudo, key-ignoring nested document search
    'relation.$.status': 'friends'
}
var projection = {
    'relation': 1
}
db.user.findOne(query, projection)

期望的输出:

{ 
    "2b2b2b2b2b2b2b2b2b2b2b": {
       "status": 'friends',
       "status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
       // etc...
    }
}

对用户数据结构的明显更正应该是创建relation一个对象数组,其中包含_idstatus作为键。有点在这里寻找临时垫片。

4

1 回答 1

1

您可以为此任务应用 mongodb Map/Reduce技术。

1)map函数将从对象中确定嵌套对象relation,其中包含status等于"friends"值的字段:

var map = function () {
    for (var key in this.relation) {
        var relation = this.relation[key];
        if (relation.status == "friends")
            emit(key, relation);
    }
}

2)reduce函数实际上什么都不做,只返回单个发出的关系:

var reduce = function (key, values) {
    return values[0];
}

结果,您将收集到此类对象:

{
  _id: "2b2b2b2b2b2b2b2b2b2b2b",
  value: {
    status: "friends",
    status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
    // etc...
  }
}

如果你决定relation用数组替换对象,你可以使用聚合框架来构造类似的查询。

用户数据:

{
    _id: ObjectId("1a1a1a1a111a1a11a1a1a1a"),
    name: "Tester",
    relations: [
        {
            id: "2b2b2b2b2b2b2b2b2b2b2b",
            status: "friends",
            status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
            // etc...
        },
        {
            id: "3c3c3c3c3c3c3c3c3c3c3c",
            status: "engaged",
            status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
            // etc...
        }
    ]
}

询问:

db.collection.aggregate([
    { $unwind: "$relations" },
    { $match: { "relations.status": "friends" } },
    { $project: _id: 0,
        id: "$relations.id",
        status: "$relations.status",
        status_changed_date: "$relations.status_chaged_date"
        // etc...
    }
])

输出:

{
  id: "2b2b2b2b2b2b2b2b2b2b2b",
  status: "friends",
  status_changed_date: ISODate("2013-10-28T00:00:00.0000Z"),
  // etc...
}
于 2013-10-30T15:11:52.423 回答