简体   繁体   English

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

[英]mongodb get _id as string in find query

Here I have created a collection with a single document 在这里,我用一个文档创建了一个集合

db.getCollection('example').insert({"example":1});

I have tried to use Projection, and I get back the _id. 我尝试使用Projection,然后返回_id。

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

{
    "_id" : ObjectId("562a6300bbc948a4315f3abc")
}

However, I need the below output as shown below. 但是,我需要以下输出,如下所示。

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

    { "id" : "562a6300bbc948a4315f3abc" }

Although I can process #1 and #2 on my app server(PHP based) to get the desired ouput, I am looking if there is a way to get the expected result on querying from mongo itself 尽管我可以在我的应用服务器(基于PHP)上处理#1和#2以获得所需的输出,但我正在寻找是否有一种方法可以从mongo本身获取查询结果

MongoDB 4.0 adds the $convert aggregation operator and the $toString alias which allows you to do exactly that: MongoDB 4.0添加了$convert聚合运算符和$toString别名,使您可以精确地做到这一点:

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

A main usage would most likely be though to use the _id value as a "key" in a document. 主要用法很可能是将_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"] }
              }
            }
          }
        }] 
      ]
    }
  }}
])

Which would return: 哪个会返回:

{ 
  "5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}

Which clearly shows the string, as does the other example. 就像其他示例一样,它清楚地显示了字符串。

Generally though there is usually a way to do "transforms" on the cursor as documents are returned from the server. 通常,虽然通常有一种方法可以在光标从服务器返回文档时对光标进行“转换”。 This is usually a good thing since an ObjectId is a 12-byte binary representation as opposed to a 24 character hex "string" which takes a lot more space. 这通常是一件好事,因为ObjectId是12字节的二进制表示形式,而不是需要占用更多空间的24字符十六进制“字符串”。

The shell has a .map() method 外壳具有.map()方法

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

And NodeJS has a Cursor.map() which can do much the same thing: Cursor.map()有一个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
})

And the same method exists in other drivers as well ( just not PHP ), or you can just iterate the cursor and transform the content as is more likely the best thing to do. 同样的方法也存在于其他驱动程序中(只是不存在PHP),或者您可以迭代游标并转换内容,这可能是最好的做法。


In fact, whole cursor results can be reduced into a single object with great ease by simply adding to any cursor returning statement, when working in the shell 实际上,在shell中工作时,只需将任何游标返回语句添加到任何游标返回语句中,就可以轻松地将整个游标结果简化为单个对象

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

Or for full ES6 JavaScript supporting environments like nodejs: 或对于完整的ES6 JavaScript支持环境,例如nodejs:

.toArray().reduce((o,({ _id, ...e })) =>  ({ ...o, [_id]: e }),{ })

Really simple stuff without the complexity of what needs to process in the aggregation framework. 真正简单的东西,没有聚合框架中需要处理的内容的复杂性。 And very possible in any language by much the same means. 而且几乎可以通过任何相同的方式使用任何语言。

You need to use the .aggregate() method. 您需要使用.aggregate()方法。

db.getCollection('example').aggregate([ { "$project": { "_id": 0, "id": "$_id" } } ]);

Which yields: 产生:

{ "id" : ObjectId("562a67745488a8d831ce2e35") }

or using the .str property. 或使用.str属性。

db.getCollection('example').find({"example":1},{"_id":1}).map(function(doc) { 
    return {'id': doc._id.str }
})

Which returns: 哪个返回:

[ { "id" : "562a67745488a8d831ce2e35" } ]

Well if you are using the PHP driver you can do something like this: 好吧,如果您使用的是PHP驱动程序,则可以执行以下操作:

$connection = new MongoClient();
$db = $connection->test;
$col = $db->example;
$cursor = $col->find([], ["_id" => 1]);
foreach($cursor as $doc) { print_r(array("id" => $doc["_id"])); } 

Which yields: 产生:

Array
(
    [id] => MongoId Object
        (
            [$id] => 562a6c60f850734c0c8b4567
        )

)

Or using again the MongoCollection::aggregate method. 或再次使用MongoCollection::aggregate方法。

$result = $col->aggregate(array(["$project" => ["id" => "$_id", "_id" => 0]]))

Then using the foreach loop: 然后使用foreach循环:

Array
(
    [_id] => MongoId Object
        (
            [$id] => 562a6c60f850734c0c8b4567
        )

)

One simple solution for traversing MongoCursor on PHP side is to use Generators as well as foreach or array_map($function, iterator_to_array($cursor)) . 在PHP上遍历MongoCursor的一种简单解决方案是使用Generators以及foreacharray_map($function, iterator_to_array($cursor)) Example: 例:

function map_traversable(callable $mapper, \Traversable $iterator) {
    foreach($iterator as $val) {
        yield $mapper($val);
    }
}

You can meet more at PHP documentation about generators syntax . 您可以在PHP文档中了解有关生成器语法的更多信息

So, now you can use/reuse it (or similar implementation) for any propose of "projecting" your data on PHP side with any amount of mapping (just like pipeline does in aggregate ) but with fewer iterations amount. 因此,现在您可以使用/重用它(或类似的实现),以进行任何具有任意数量的映射(就像管道进行aggregate )一样在PHP端“投影”数据的建议,而迭代次数则更少。 And this solution is pretty convenient for OOP in a case of reusing your map functions. 在重用map功能的情况下,此解决方案对于OOP来说非常方便。

UPD: Just for your case example below: UPD:仅针对您的以下案例:

$cursor = $db->getCollection('example')->find(["example":1],["_id":1]);
$mapper = function($record) {
    return array('id' => (string) $record['_id']); //see \MongoId::__toString()
}
$traversableWithIdAsStringApplied = map_traversable($mapper, $cursor);
//...

now you can proceed with more mappings applied to $traversableWithIdAsStringApplied or use just iterator_to_array for simple array retrieving. 现在,您可以继续将更多映射应用于$ traversableWithIdAsStringApplied或仅使用iterator_to_array进行简单的数组检索。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM