Obtenha o _id do documento inserido no banco de dados Mongo em NodeJS


100

Eu uso o NodeJS para inserir documentos no MongoDB. Usando collection.insertposso inserir um documento no banco de dados como neste código:

// ...
collection.insert(objectToInsert, function(err){
   if (err) return;
   // Object inserted successfully.
   var objectId; // = ???
});
// ...

Como posso obter o _idobjeto inserido?

Existe alguma maneira de obter o _idobjeto sem inserir o último _id?

Supondo que ao mesmo tempo muitas pessoas acessem o banco de dados, não posso ter certeza se o id mais recente é o id do objeto inserido.

Respostas:


88

Existe um segundo parâmetro para o retorno de chamada para collection.insertque retornará o documento ou documentos inseridos, que devem ter _ids.

Experimentar:

collection.insert(objectToInsert, function(err,docsInserted){
    console.log(docsInserted);
});

e verifique o console para ver o que quero dizer.


4
O retorno de chamada realmente retorna a matriz de documentos inseridos. Portanto, se você inseriu um único documento, poderá acessar o registro inserido conforme abaixo. coleção.insert ({nome: "David", título: "Sobre MongoDB"}, função (err, registros) {console.log ("Registro adicionado como" + registros [0] ._ id);}); Ref: mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
Rohit Singh Sengar


link não leva a nenhum lugar útil
davidhadas

Não sei se isso é geral ou só funciona em meteoro, mas quando você chama collection.insert (objeto), ele retorna o id do objeto inserido imediatamente.
vantesllar

4
docsInserted não retorna um _id para mim. ele retorna para mim {"ok": 1, "n": 1, "opTime": {"ts": "6361004504208375809", "t": 5}, "selectionId": "7fffffff0000000000000005"}
user1709076

90

Uma maneira mais curta do que usar o segundo parâmetro para o retorno de chamada de collection.insertseria usar objectToInsert._idque retorna o _id(dentro da função de retorno de chamada, supondo que foi uma operação bem-sucedida).

O driver Mongo para NodeJS anexa o _idcampo à referência do objeto original, portanto, é fácil obter o id inserido usando o objeto original:

collection.insert(objectToInsert, function(err){
   if (err) return;
   // Object inserted successfully.
   var objectId = objectToInsert._id; // this will return the id of object inserted
});

4
Muito perspicaz, obrigado. Não foi possível encontrar essas informações em nenhum outro lugar desde a mudança nos parâmetros de retorno de chamada.
Brad Hein

@BradHein De nada! Provavelmente, o driver MongoDB modifica a referência do objeto, portanto, ele também é modificado aqui. :)
Ionică Bizău

Seu código está errado, onde você diz var objectId = objectToInsert._id; você quis dizer var objectId = objectInserted._id;
Andy Lorenz

3
@AndyLorenz O que é objectInserted? Eu acho que você está perdendo exatamente o ponto desta resposta: o driver Mongo anexa o _idcampo ao objeto original. Editei a resposta para usar em objectToInsertqualquer lugar. Espero que as coisas estejam mais claras agora. :)
Ionică Bizău

1
NOTA: insert()está obsoleto. Use em insertOne()vez disso
evilReiko

16

Como disse o ktretyak, para obter o ID do documento inserido, a melhor maneira é usar a propriedade insertId no objeto de resultado. No meu caso, result._id não funcionou, então tive que usar o seguinte:

db.collection("collection-name")
  .insertOne(document)
  .then(result => {
    console.log(result.insertedId);
  })
  .catch(err => {
    // handle error
  });

É a mesma coisa se você usar callbacks.


13

Na verdade, fiz um console.log () para o segundo parâmetro na função de retorno de chamada para inserir. Na verdade, há muitas informações retornadas além do próprio objeto inserido. Portanto, o código abaixo explica como você pode acessar seu id.

collection.insert(objToInsert, function (err, result){
    if(err)console.log(err);
    else {
        console.log(result["ops"][0]["_id"]);
        // The above statement will output the id of the 
        // inserted object
       }
});

Isso resulta em um ObjectID {_bsontype: "ObjectID", id: Buffer(12)}. Como posso usá-lo para obter a id real que está no banco de dados? ... A resposta foi encontrada em outro comentário: Usoresult.insertedId.toString()
Fadwa

7

O Mongo envia o documento completo como um objeto de retorno de chamada para que você possa simplesmente obtê-lo apenas a partir daí.

por exemplo

collection.save(function(err,room){
  var newRoomId = room._id;
  });

4

Agora você pode usar o método insertOne e no result.insertedId da promessa


Você poderia fornecer um exemplo de código? De onde vem esse objeto de resultado?
JSideris de

@JSideris, como você pode ver no método de especificação insertOne () , este método aceita três parâmetros (doc, options, callback). O terceiro parâmetro - um retorno de chamada, que leva dois parâmetros (error, result) . E result- é isso que você está procurando.
ktretyak

2

@JSideris, código de amostra para obter o insertId.

db.collection(COLLECTION).insertOne(data, (err, result) => {
    if (err) 
      return err;
    else 
      return result.insertedId;
  });

2

se você quiser pegar "_id" use simpley

result.insertedId.toString() 

// toString irá converter de hexadecimal


É isso que eu estava procurando. Obrigado.
Fadwa

Sim, deve ter havido uma mudança de versão, pois as outras respostas não mencionam result.insertedIdé um ObjectIDobjeto de tipo. .toString()irá converter este objeto em um UUID real.
Dylan Pierce

0

Você pode usar funções assíncronas para obter o campo _id automaticamente sem manipular o objeto de dados:

async function save() {
  const data = {
    name: "John"
  }

  await db.collection('users', data )

  return data
}

Retorna dados:

{
  _id: '5dbff150b407cc129ab571ca',
  name: 'John'
}

0

Outra maneira de fazer isso na função assíncrona:

const express = require('express')
const path = require('path')
const db = require(path.join(__dirname, '../database/config')).db;
const router = express.Router()

// Create.R.U.D
router.post('/new-order', async function (req, res, next) {

    // security check
    if (Object.keys(req.body).length === 0) {
        res.status(404).send({
            msg: "Error",
            code: 404
        });
        return;
    }

    try {

        // operations
        let orderNumber = await db.collection('orders').countDocuments()
        let number = orderNumber + 1
        let order = {
            number: number,
            customer: req.body.customer,
            products: req.body.products,
            totalProducts: req.body.totalProducts,
            totalCost: req.body.totalCost,
            type: req.body.type,
            time: req.body.time,
            date: req.body.date,
            timeStamp: Date.now(),

        }

        if (req.body.direction) {
            order.direction = req.body.direction
        }

        if (req.body.specialRequests) {
            order.specialRequests = req.body.specialRequests
        }

        // Here newOrder will store some informations in result of this process.
        // You can find the inserted id and some informations there too.
        
        let newOrder = await db.collection('orders').insertOne({...order})

        if (newOrder) {

            // MARK: Server response
            res.status(201).send({
                msg: `Order N°${number} created : id[${newOrder.insertedId}]`,
                code: 201
            });

        } else {

            // MARK: Server response
            res.status(404).send({
                msg: `Order N°${number} not created`,
                code: 404
            });

        }

    } catch (e) {
        print(e)
        return
    }

})

// C.Read.U.D


// C.R.Update.D


// C.R.U.Delete



module.exports = router;
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.