mongodb 插入之后怎样获取id

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongodb 插入之后怎样获取id相关的知识,希望对你有一定的参考价值。

我在mongodb中插入了一条记录,怎么获取这条记录的_id号,_id是自动生成的,插入的记录不是唯一的,只有自动生成的_id是唯一的。所以不能先插入之后,再去find。坐等结果。。

参考技术A 你可以自己指定_id 不用让mongo自动生成 参考技术B 两种方式提供你生成自增ID:
第一种:使用IdGenerator属性,并在Bson特性上进行指定。
第二种:自增id生成器。这个需要你自己写代码来实现,原则是1个集合对应1个自增序列,并使用MongoShell自带的$inc进行原子自增操作(更新后再获取FindAndModify)。

根据你的需求,你应该当选择第二种方法。可以利用反射将每一个实体类对应的集合去让其自动生成自增集合;或者由一个集合容器来统一管理所有需要自增的集合的自增序列。本回答被提问者采纳
参考技术C 我也遇到这个问题,能否帮忙说一下怎么实现的,谢谢

Node.js | MongoDB count():在插入数据之前和之后获取计数

【中文标题】Node.js | MongoDB count():在插入数据之前和之后获取计数【英文标题】:Node.js | MongoDB count(): Getting Count Before and After Inserting Data 【发布时间】:2017-01-21 16:37:02 【问题描述】:

我正在尝试获取数据库中的项目计数以确认数据插入成功。

    插入前获取计数 插入 插入后获取计数 Console.log 总结

注意:我知道这可以使用一些简单的函数来实现:

dbName.equal(insertSize, result.insertedCount)

但是,我是 javascript 新手,我想我遇到了实现异步回调的需要,所以我想弄清楚这一点。

插入函数

var insertMany = function() 

    // get initial count
    var count1 = getDbCount();

    // Insert new 'data'
    MongoClient.connect(url, function(err, db) 
        var col = db.collection(collectionName);
        col.insert(data, w:1, function(err,result) );
        db.close();
    );

    /** This needs to be implemented through next/callback
        after the insert operation  **/
    var count2 = getDbCount(); 

    /** These final console logs should be executed after all
        other operations are completed **/    
    console.log('[Count] Start: ' + count1 + ' | End:' +count2);
    console.log('[Insert] Expected: ' + data.length + ' | Actual: ' + (count2 - count1));

;

获取数据库计数函数

var getDbCount = function() 
    MongoClient.connect(url, function(err, db) 
        if (err) console.log(err);

        var col = db.collection(collectionName);

        col.count(, function(err, count) 
            if (err) console.log(err);
            db.close();
            console.log('docs count: ' + count);
            // This log works fine
        );

    );

    return count; // this is returning as undefined since this is
                  // executing before the count operation is completed
;

我收到错误,因为在所需操作完成之前发生退货。

感谢您的帮助。


[EDIT] 带有 Promise 的 getCount 函数

我已将承诺添加到 getCount 函数作为开始:

var getCount = function() 

    var dbCount = 0;

    var promise = new Promise(function(resolve, reject) 

        MongoClient.connect(url, function(err, db) 

            if (err) 
                console.log('Unable to connect to server', err);
             else 
                console.log('Database connection established:' + dbName);
            

            // Get the collection
            var col = db.collection(collectionName);

            col.count(, function(err, count) 
                if (err) console.log(err);
                db.close();
                console.log('docs count: ' + count);
                resolve(null);
                dbCount = count;
            );

        );

    );

    promise.then(function() 
        return dbCount;
    );

;

console.log(getCount());

输出仍然是: 不明确的 建立数据库连接:testdb 文档数:500

then(return count) 代码仍然在 promise db.count() 之前执行。在数据库操作完成之前返回 undefined。

【问题讨论】:

如果你不展示你尝试过的东西,就很难说出你做错了什么。该错误应该带有一些关于错误发生在哪一行的信息。提供发生错误的代码块以及至少调用它的部分 嗨 newBee,我已经把它拿出来了。我在通过回调实现方面没有取得太大进展,这就是我没有包含它的原因。如果我取得进展,我将更新并添加新代码。谢谢 @CarloP.LasMarias 你永远不应该选择setTimeout。有很多文章专门在后端解释了该功能的暴行。 Promise 是为处理此类情况而开发的模块,如果它不起作用,则问题出在代码中,需要解决。 Async.js 是另一个比 setTimeout 更好的选择。 【参考方案1】:

一般来说,您遇到的问题是您希望函数返回时该值已经存在。对于异步函数,情况通常并非如此。有大量关于异步处理的信息(不要与 Java 中的并行处理相混淆)。

我创建了一个适合您情况的示例:

https://jsfiddle.net/rh3gx76x/1/

var dummyCount = 5
getCount = function() 
    return new Promise(function(resolve, reject) 
      setTimeout(function()  // this would be your db call, counting your documents
          resolve(dummyCount); // dummy for number of documents found
      , 100 * Math.random());
  );
;

insertMany = function() 
    return new Promise(function(resolve, reject) 
      setTimeout(function()  // this would be your db call, writing your documents
          dummyCount += 2;
          resolve();
      , 100 * Math.random());
  );
;

runIt = function(callback) 
   var count1;
   getCount().then(function(count) 
        console.log("First callback with value ", count);
      count1 = count;
        insertMany().then(function() 
         getCount().then(function(count2)
            console.log("Second callback with value ", count2);
                callback(null, count1, count2);
         );
      )
   )


runIt(function(err, count1, count2) 
   console.log("count1: " + count1 + ", count2: " + count2);
);

最后一件事。您可能想查看“异步”包。提供大量辅助函数和控制流的东西,这对解决这些问题有很大帮助。

【讨论】:

setTimeout 是一种糟糕的做法。不建议专门在 I/O 任务中使用超时。您通过随机延迟代码来消耗时间。这会在开发复杂网站时消耗您的资源。 @Ritik Saxena 此处的超时只是替换原始海报制作的数据库调用,使示例更易于阅读。无法在您也没有提到的资源问题上关注您。将代码延迟到下一个事件循环滴答声并不少见。尽管您当然会始终使用“0”超时。 @newBee 通过使用 setTimeout 代替 db 调用以使示例更易于阅读,我希望您并不是说添加它是为了使示例更具可读性,没有任何其他目的。你是否?此外,reject 用于传递 promise 中的错误,这些错误在 catch 语句中处理。因此,您可能需要编辑注释 null = no error,因为此处的 null 表示代码没有任何内容可传递给 then @newBee 我不完全明白你为什么使用超时。实际上,超时在后端是一种不常见的做法。在这种情况下,您的代码可能会起作用,但是在程序读取/写入数据库所花费的时间取决于数据库大小的情况下,您将设置一个随机的超时时间并希望最好的发生。因此,您的代码可能在这里可以工作,但这并不是一个始终遵循的好习惯。 @RitikSaxena 写了你的第一个回复:调用 runIt 函数时我没有回传 Promise。您误解了程序的流程。一般来说,使用承诺或回调方法是一个偏好问题。这里的超时只是为了模拟任何异步操作(例如磁盘 IO 或 DB 调用),因此提供了一个更通用的示例。 w.r.t 你的第二个问题:有些用例需要那些(或类似的函数,如 setImmediate)。例如。一次调用大量回调时。这可能会导致stack overflow 错误。【参考方案2】:

在操作完成之前就发生返回的原因是nodejs的asynchronous设计,继承自javascript。来自Mongoose.connect() 的回调将在程序向前移动并遇到return 时进行操作。

您尚未提供使您进入错误声明的解决方法,因此我无法评论您在那里做错了什么。但是,考虑到您首先要完成您开始的工作,确保Mongoose.connect() 完成然后执行return 语句的最佳方法是使用JavaScript 的promise。使用 Promise 将使您的 Mongoose.connect() 执行,然后将控制权传递给 return 语句。

您的代码将类似于:

插入函数

var insertMany = function() 

// get initial count
var count1 = getDbCount();

// Insert new 'data'
var promise = new Promise(
    function(resolve,reject)
      MongoClient.connect(url, function(err, db) 
        var col = db.collection(collectionName);
        col.insert(data, w:1, function(err,result) );
        db.close();
        resolve(null);
      );
    
  );
  promise.then(function(val)    
    var count2 = getDbCount();

    /** These final console logs should be executed after all
    other operations are completed **/
    console.log('[Count] Start: ' + count1 + ' | End:' +count2);
    console.log('[Insert] Expected: ' + data.length + ' | Actual: ' + (count2 - count1));
);

同样,您可以将 promise 添加到 GetDB 函数。 执行 Promise 时的关键点是:

    then() 包含了 promise 执行后要同步执行的部分函数。被resolve调用,传入的参数在catch函数的回调中接收。 catch() 包含在 Promise 中遇到错误时调用的函数部分。由reject调用,传入的参数在catch函数的回调中接收。

编辑:promise 的替代品是async.js,唯一的区别在于它是一个外部模块,与promise 不同。

【讨论】:

请注意,此代码仍然会失败。 count2 将具有值“未定义” @newBee 在我写完代码之后,我提到GetDB 也必须以这种方式执行。然后,count 就会有一个值返回给 count2。 谢谢@RitikSaxena,我试过了,但仍然遇到同样的错误。即使在添加了 Promise 之后,then 语句仍然在 Promise 之前执行。我已经在修改后的 getCount 上面添加了。 @CarloP.LasMarias 您正在调用resolve,然后为dbCount 赋值。所以你的dbCount 永远不会被分配。试试这个:将null 替换为count 在解析中。在then函数的回调中,接收一个参数并赋值给dbCount @RitikSaxena 我试过 resolve(count); dbCount = count;,也颠倒了顺序。结果还是一样,dbCount = undefined。

以上是关于mongodb 插入之后怎样获取id的主要内容,如果未能解决你的问题,请参考以下文章

怎样在linux的shell脚本中连接mongodb插入

MongoDB怎样批量执行命令

在 Mongodb 数组中,有没有办法在特定元素位置之前/之后插入新元素

在 Mongodb 数组中,有没有办法在特定元素位置之前/之后插入新元素

通过JAVA在mongodb中获取currentdate

如何使用 mongoDb java 异步驱动程序插入 mongoDb 集合后获取 _id