mongodb在查找查询中将_id作为字符串获取

Fai*_*eef 5 php mongodb mongodb-query aggregation-framework

在这里,我用一个文档创建了一个集合

db.getCollection('example').insert({"example":1});
Run Code Online (Sandbox Code Playgroud)

我尝试使用Projection,然后返回_id。

db.getCollection('example').find({"example":1},{"_id":1});

{
    "_id" : ObjectId("562a6300bbc948a4315f3abc")
}
Run Code Online (Sandbox Code Playgroud)

但是,我需要以下输出,如下所示。

  1. id而不是_id
  2. ObjectId(“ 562a6300bbc948a4315f3abc”)vs“ 562a6300bbc948a4315f3abc”

    { "id" : "562a6300bbc948a4315f3abc" }

尽管我可以在我的应用服务器(基于PHP)上处理#1和#2以获得所需的输出,但是我正在寻找是否有一种方法可以从mongo本身获取查询结果

Nei*_*unn 12

MongoDB 4.0 添加了$convert聚合运算符和$toString别名,它允许您完全做到这一点:

db.getCollection('example').aggregate([
  { "$match": { "example":1 } },
  { "$project": { "_id": { "$toString": "$_id" } } }
])
Run Code Online (Sandbox Code Playgroud)

主要用途很可能是将该_id值用作文档中的“键”。

db.getCollection('example').insertOne({ "a": 1, "b": 2 })

db.getCollection('example').aggregate([
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": [
        [{ 
          "k": { "$toString": "$_id" },
          "v": {
            "$arrayToObject": {
              "$filter": {
                "input": { "$objectToArray": "$$ROOT" },
                "cond": { "$ne": ["$$this.k", "_id"] }
              }
            }
          }
        }] 
      ]
    }
  }}
])
Run Code Online (Sandbox Code Playgroud)

哪个会返回:

{ 
  "5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}
Run Code Online (Sandbox Code Playgroud)

这清楚地显示了字符串,就像另一个例子一样。

通常,尽管通常有一种方法可以在从服务器返回文档时对光标进行“转换”。这通常是一件好事,因为 anObjectId是 12 字节的二进制表示,而不是 24 个字符的十六进制“字符串”,后者占用更多空间。

shell有.map()方法

db.getCollection('example').find().map(d => Object.assign(d, { _id: d._id.valueOf() }) )
Run Code Online (Sandbox Code Playgroud)

NodeJS 有一个Cursor.map()可以做很多相同的事情:

let cursor = db.collection('example').find()
    .map(( _id, ...d }) => ({ _id: _id.toString(), ...d }));

while ( await cursor.hasNext() ) {
  let doc = cursor.next();
  // do something
})
Run Code Online (Sandbox Code Playgroud)

同样的方法也存在于其他驱动程序中(只是不是 PHP ),或者您可以迭代光标并转换内容,这更有可能是最好的做法。


实际上,在 shell 中工作时,只需将整个游标结果添加到任何游标返回语句中,就可以轻松地将其简化为单个对象

.toArray().reduce((o,e) => { 
  var _id = e._id;
  delete e._id;
  return Object.assign(o, { [_id]: e })
},{ })
Run Code Online (Sandbox Code Playgroud)

或者对于像 nodejs 这样的完整 ES6 JavaScript 支持环境:

.toArray().reduce((o,({ _id, ...e })) =>  ({ ...o, [_id]: e }),{ })
Run Code Online (Sandbox Code Playgroud)

真正简单的东西,没有需要在聚合框架中处理的复杂性。并且通过几乎相同的方式在任何语言中都非常可能。