mongodb - MongoDB 中的嵌套文档值搜索

标签 mongodb nested document

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

需要找到一种方法在 user 集合的 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...
    }
}

User Data 结构的明显修正应该是使relation 成为一个对象数组,其中包含_idstatus 作为键。有点想在这里找一个临时垫片。

最佳答案

可以申请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 对象,您可以使用aggregation framework构建类似的查询。

用户数据:

{
    _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...
}

关于mongodb - MongoDB 中的嵌套文档值搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19666584/

相关文章:

php - Mongodb 按天聚合组(php)

mongodb - 在Mongodb上使用Grails时是否存在连接泄漏

java - Morphia 中的 @Embedded 注释实际上有什么作用?

html - 嵌套 Bootstrap 行和列

linux - 嵌套的 if/then/elseif 在 bash 中如何工作?

document - Microstrategy - 仪表板和文档

java - 随着 upsert 的推移,Mongodb 性能会显着下降。

ruby - 如何在 ruby​​ 中动态设置嵌套哈希?

javascript - 包装文档或窗口对象以检查滚动值?