Node.js Mongodb 回调问题

Posted

技术标签:

【中文标题】Node.js Mongodb 回调问题【英文标题】:Node.js Mongodb Callback issue 【发布时间】:2015-11-01 05:16:39 【问题描述】:

如果 tmx 较新,则我的应用程序应该更新,如果较旧则什么也不做,如果不存在则插入文档。 如果文档被插入,它可以正常工作,否则它不能正确更新或显示 E11000 dup key。 试图弄清楚我的回调是错误的还是逻辑错误。 (我是 node.js+mongodb 的新手) MongoClient = require('mongodb').MongoClient, 断言 = 要求('断言'), url = 'mongodb://localhost:27017/pfc';

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


    function run(db) 
        fs.readFile('log.log', 'utf8', function (err, source) 
            if (err) throw err;
            var dataFile = JSON.parse(source);
            dataFile.forEach(function (item) 
                upsert(db, item, function (err, result) 
                    if (err) console.dir(err);

                );
            );
        )
    

    function upsert(db, doc, callback) 

    db.collection('flags').findOne(vid: doc.vid, function (err, item, result) 

        if (item.vid != null) 
            if (!(item.tmx instanceof Date)) 
                item.tmx = new Date(item.tmx)
            
            if(!(doc.tmx instanceof Date))
                doc.tmx = new Date(doc.tmx)
            

            if (item.tmx < doc.tmx) 
                console.dir("Date validation")
                db.collection('flags').updateOne(vid: item.vid, 
                        $set: 
                            "tmx": doc.tmx
                        
                    ,upsert:true, function (err, result) 
                        callback(err, result);

                    
                )

                callback(err, result);
            
            else
                console.dir("older")
                callback(err, result);
            
        
        else 
            db.collection('flags').insertOne(doc, function(err, result) 
                callback(err, result);
            );
        
    )

编辑: “log.log”文件中的文档具有以下结构:

视频:2848 tmx:“2015-07-18T23:56:17.000Z”

视频:2848 tmx: 2015-07-19T00:00:17.000Z

collection.find(vid: doc.vid,function(err,item)

if(!item) // 在集合中没有找到,带有 vid 的项目:2848 将文档插入集合 else if(item) //找到一个带有 vid:2848 的项目 if (item.tmx

在@Aaron Dufour 的帮助下,我摆脱了回调问题,谢谢 :) 但是现在的问题是,当我已经填充了集合并在 log.log 中查找最新文档时,它会从最旧的文档开始直到最新的文档:(

【问题讨论】:

您的 upsert 逻辑容易受到竞争条件的影响,这可能会导致问题。你试过 Mongo 的内置 upsert 吗? 当我必须比较要更新的日期时,看不到如何使用它 因为如果项目不存在,我会得到 item.tmx 属性为空错误,所以我需要确认项目存在,以便我可以将文件中的日期与 mongodb 中的日期进行比较跨度> 您是否有多个具有相同vid 值的文档? 是的,我有。该文件现在有超过 60000 个文档,我平均有 40 个具有相同 vid 的文档 【参考方案1】:

您的upsert 容易受到竞争条件的影响,run 会同时多次调用它,所以这可能是问题所在。目前尚不清楚doc 的具体外观,因此您可能需要稍微复杂一点的逻辑,但这里有一个使用Mongo 的upsert 的版本让事情变得更安全:

function upsert(db, doc, callback) 
  db.collection('flags').update(vid: doc.vid, $set: doc, upsert: true, function(err) 
    db.collection('flags').update(vid: doc.vid, tmx: $lt: doc.tmx, $set: tmx: doc.tmx, function(err) 
      callback();
    );
  );

【讨论】:

m8 你是个天才,救了我的命:D 发现了一个小错误,例如,最早的记录是从 07/08/2015 00:00:17 开始的,最新的记录是从今天开始的。如果我再次运行该应用程序,它将更新到最旧的并再次进入新的,我尝试的方法不起作用。 :(如何避免这种情况? @TelmoIvo 我不明白你遇到的问题。也许将其编辑到问题中,以便您有更多的空间来解释它? 在问题末尾添加了更多详细信息。

以上是关于Node.js Mongodb 回调问题的主要内容,如果未能解决你的问题,请参考以下文章

Node.js mongodb 驱动程序异步/等待查询

node js mongodb回调不起作用-下面的代码在我的笔记本电脑上有效,但在另一台PC上无效

node.js async.eachSeries 过早调用最终回调

[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist

Node.js学习四 Node.js回调函数

Node.js 监听 MongoDB 变化