简体   繁体   English

mongodb - 带有nodejs的上限集合

[英]mongodb - capped collections with nodejs

I'm trying to set up and update some capped collections in MongoDB using Node.js (using the native MongoDB driver). 我正在尝试使用Node.js(使用本机MongoDB驱动程序)在MongoDB中设置和更新一些上限集合。 My goal is to, upon running app.js, insert documents into a capped collection, and also to update existing documents in a capped collection. 我的目标是,在运行app.js时,将文档插入到上限集合中,并更新上限集合中的现有文档。 Both of these are running on setInterval() , so every few seconds. 这两个都在setInterval()上运行,所以每隔几秒钟。

My questions: 我的问题:

  1. I want to create a collection if the collection does not already exist, but if it does I want to insert a document into it instead. 如果集合尚不存在,我想创建一个集合,但如果它确实存在,我想要将文档插入其中。 What is the correct way to check this? 检查这个的正确方法是什么?
  2. With capped collections, should I even be explicitly creating them first before inserting anything into them? 对于上限集合,我是否应该在插入任何内容之前先显式创建它们? Normally I believe you can just insert things into a collection without explicitly creating them first, but in this case I need to ensure they are capped. 通常情况下,我相信您可以直接将内容插入到集合中,而无需先显式创建它们,但在这种情况下,我需要确保它们有上限。 Once the capped collection exists I know how to insert new documents into it, the problem is I need some way to handle the app being used for the first time (on a new server) where the collection doesn't already exist, and I want to do this creation using node and not having to jump into the mongo cli. 一旦存在上限集合,我知道如何在其中插入新文档,问题是我需要一些方法来处理第一次使用的应用程序(在新服务器上),其中集合尚不存在,我想要使用节点进行此创建,而不必跳转到mongo cli。
  3. The trick here is that the collection needs to be capped, so I can do something like: db.createCollection("collectionName", { capped : true, size : 100000, max : 5000 } ) . 这里的诀窍是集合需要上限,所以我可以做类似的事情: db.createCollection("collectionName", { capped : true, size : 100000, max : 5000 } ) That will create the capped collection for me, but every time I call it it will call createCollection() instead of updating or inserting - if I call createCollection() , once the collection already exists, will it completely overwrite the existing collection? 这将为我创建上限集合,但每次调用它时都会调用createCollection()而不是更新或插入 - 如果我调用createCollection() ,一旦集合已经存在,它是否会完全覆盖现有集合?
  4. An alternative is to turn a collection into a capped one with: db.runCommand({"convertToCapped": "collectionName", size: 100000, max : 5000 }); 另一种方法是使用以下命令将集合转换为上限: db.runCommand({"convertToCapped": "collectionName", size: 100000, max : 5000 }); . The problem with this is that node doesn't see runCommand() as a valid function and it errors. 这个问题是节点没有看到runCommand()作为有效函数而且它出错。 Is there something else that I'm meant to be calling to get this to work? 是否有其他东西我打算要求它让这个工作? It works in the mongo cli but not within node 它适用于mongo cli但不在节点内
  5. What type of query do you use to find the first document in a collection? 您使用什么类型的查询来查找集合中的第一个文档? Again, within the mongo cli I can use db.collections.find() with some query, but within node it states that find() is not a valid function 同样,在mongo cli中我可以使用db.collections.find()和一些查询,但在节点内它声明find()不是有效的函数
  6. How would I use collection.update() to add some new fields to an existing document? 我如何使用collection.update()向现有文档添加一些新字段? Lets say the document is some simple object like {key1: "value", key2: "value"} but I have an object that contains {key3: "value"} . 让我们说文档是一些简单的对象,如{key1: "value", key2: "value"}但我有一个包含{key3: "value"} Key 3 does not exist in the current document, how would I add that to what currently exists? 当前文档中不存在键3,如何将其添加到当前存在的内容中? This is somewhat related to #4 above in that I'm not sure what to pass in as the query parameter given that find() doesn't seem to play well with node. 这与上面的#4有些相关,因为我不确定将什么传递给查询参数,因为find()似乎不能很好地与节点一起使用。

Regarding your questions 1 - 4 about capped collections and creating them automatically, there are several ways to do this. 关于有关上限集合并自动创建它们的问题1 - 4,有几种方法可以做到这一点。 On the one hand, you could run a script to initialise your database so that it has the capped collections available to your client when you run it for the first time. 一方面,您可以运行一个脚本来初始化您的数据库,以便在您第一次运行它时,它可以为您的客户端提供上限集合。 On the other hand, you could have a check to see if there are any documents in the given collection before inserting a document. 另一方面,在插入文档之前,您可以检查给定集合中是否有任何文档。 If there are, you just insert your document and if there aren't, you create the capped collection and then insert the document as a callback to that function. 如果有,您只需插入文档,如果没有,则创建上限集合,然后将文档作为回调插入该函数。 It would work something like this: 它会像这样工作:

var host = "localhost",
port = 27017,
dbName = "so";

var MongoClient = require('mongodb').MongoClient, Server = require('mongodb').Server;
var mongoclient = new MongoClient(new Server(host, port));
var db = mongoclient.db(dbName);

db.open(function(err, db) {

    if(err) throw err;

    // Capped collection.
    var capped = db.collection('capped');

    // Document to be inserted.
    var document =  { "foo": 1, "bar": 1 }

    capped.find().count(function(err, count) {

        if(err) throw err;

        if (count === 0) {          
            console.log("Creating collection...");
            db.createCollection("capped",
                                { "capped": true,
                                  "size": 100000,
                                  "max": 5000 },
                                function(err, collection) {
                if(err) throw err;              

                // Insert a document here.
                console.log("Inserting document...");
                collection.insert(document, function(err, result) {
                    if (err) throw err;                 
                });
            });

        } else {

            // Insert your document here without creating collection.
            console.log("Inserting document without creating collection...");
            capped.insert(document, function(err, result) {
                if (err) throw err;             
            });
        }

    });
});

Regarding question 5, you can use findOne() to find a document in the collection, though this is not necessarily the first or last. 关于问题5,您可以使用findOne()在集合中查找文档,但这不一定是第一个或最后一个。 If you want to guarantee the first or last, you can run a find() with a sort() and limit() of 1. Sorting by _id ascending should give you the first document. 如果要保证第一个或最后一个,可以使用sort()limit()运行find() 1.按_id升序排序应该为您提供第一个文档。 More information here . 更多信息在这里

// Sort 1 for ascending, -1 for descending.
capped.find().sort([["_id", 1]]).limit(1).nextObject(function(err, item) {
    console.log(item);
});

Finally for question 6, you just use the $set operator with the update() method. 最后,对于问题6,您只需将$set运算符与update()方法一起使用即可。 More information here . 更多信息在这里

capped.update({ "foo": 1 }, { "$set": { "bar": 2 } }, {}, function(err, result) {
    console.log(result);
});

Note that you can only update documents in place for capped collections, so you cannot do the insert of the extra field you mention. 请注意,您只能为封顶集合更新文档,因此您无法插入您提到的额外字段。 There are other restrictions enumerated here that you might want to be aware of. 您可能希望了解此处列举的其他限制。

[EDIT: Add updating nested fields in last document.] [编辑:在上一个文档中添加更新嵌套字段。]

If you want to update a nested field in the first or last document (use 1 or -1 in the sort, respectively), you can fetch the document, extract the _id , then perform an atomic update on that document. 如果要更新第一个或最后一个文档中的嵌套字段(分别在排序中使用1或-1),则可以获取文档,提取_id ,然后对该文档执行原子更新。 Something like this: 像这样的东西:

capped.find().sort([["_id", -1]]).limit(1).nextObject(function(err, item) {       
    if(err) throw err;
    capped.update({ "_id": item._id },
              { "$set": { "timeCollected": 15, "publicIP.ip" : "127.0.0.1" }},
              function(err, result) {

        if(err) throw err;
        console.log(result);    
    });
});  

Note that even when updating a field that exists in a document in a capped collection, you need to ensure that the new value fits in the space allocated for the document. 请注意,即使更新加盖集合中文档中存在的字段,也需要确保新值适合为文档分配的空间。 So, for example, updating a string value from "1" to "127.0.0.1" will not necessarily work. 因此,例如,将字符串值从"1"更新为"127.0.0.1"不一定有效。

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

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