MongoDB 4.0 添加了 $convert 聚合运算符和 $toString 别名,这使您可以做到这一点:
db.getCollection('example').aggregate([
{ "$match": { "example":1 } },
{ "$project": { "_id": { "$toString": "$_id" } } }
])
一个主要的用法很可能是使用_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"] }
}
}
}
}]
]
}
}}
])
哪个会返回:
{
"5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}
与其他示例一样,清楚地显示了字符串。
虽然通常有一种方法可以在从服务器返回文档时对光标进行“转换”。这通常是一件好事,因为 ObjectId 是 12 字节的二进制表示,而不是占用更多空间的 24 个字符的十六进制“字符串”。
shell 有一个.map() 方法
db.getCollection('example').find().map(d => Object.assign(d, { _id: d._id.valueOf() }) )
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
})
同样的方法也存在于其他驱动程序中(只是不是 PHP),或者您可以迭代光标并转换内容,这可能是最好的做法。
事实上,当在 shell 中工作时,通过简单地添加到任何游标返回语句中,整个游标结果可以很容易地简化为单个对象
.toArray().reduce((o,e) => {
var _id = e._id;
delete e._id;
return Object.assign(o, { [_id]: e })
},{ })
或者对于完整的 ES6 JavaScript 支持环境,例如 nodejs:
.toArray().reduce((o,({ _id, ...e })) => ({ ...o, [_id]: e }),{ })
真正简单的东西,没有聚合框架中需要处理的复杂性。并且非常可能通过几乎相同的方式使用任何语言。