Reputation: 20503
I'm wondering if there is a way to insert new document and return it in one go.
This is what I'm currently using:
db.collection('mycollection').insertOne(options, function (error, response) {
...
});
Upvotes: 54
Views: 71192
Reputation: 625
You can return the doc that you insert with the id
async insertProduct(product) {
const record = await db.collection("products").insertOne(product);
return {id: record.insertedId, ...product }
}
Upvotes: 6
Reputation: 11
As Lauren said in official mongodb forum, this is the expected behaviour. I copy here her response:
It is new in driver v4 that our driver is compliant with the MongoDB CRUD spec
When you
insertOne
you now get theinsertedId
, so that should provide the only “new” part of the document that’s handled by the database.
const myDoc = { a: 1 }
myDoc._id = (await c.insertOne(myDoc)).insertedId
// myDoc is now the same as the doc inserted into mongodb
Upvotes: 1
Reputation: 347
For those who use MongoDB driver 4.x I found a workaround with findOneAndUpdate:
const toInsert = {
_id: mongo.ObjectId(),
someField: 'hello',
someOtherField: 'world'
};
const options = { upsert: true, returnDocument: 'after' };
const { value: document } = await db.collection.findOneAndUpdate(
toInsert,
{ $set: {} },
options
);
Notice that the _id
in toInsert
is a newly generated ObjectId
.
The update is empty ({ $set: {} }
) and does nothing as we don't need to need to update, we just want to upsert our document. It's still needed because the update cant be null
or an empty object.
Because of the returnDocument
option, the newly created document will be return as value in the result.
An other solution, in order to avoid an empty update, is to use $setOnInsert
:
const toInsert = { someField: 'hello', someOtherField: 'world' };
const options = { upsert: true, returnDocument: 'after' };
const { value: document } = await db.collection.findOneAndUpdate(
{ _id: mongo.ObjectId() },
{ $setOnInsert: toInsert },
options
);
Upvotes: 11
Reputation: 16805
UPDATE 2021: This approach no longer works with the MongoDB driver 4.x. The return result of the insertOne only contains an ID and acknowledgement flag: https://mongodb.github.io/node-mongodb-native/4.1/interfaces/InsertOneResult.html
With this change, there is NO way to accomplish the required behaviour. One should either do another DB request or combine the returned insertId and original object data.
The response
result contains information about whether the command was successful or not and the number of records inserted.
If you want to return inserted data, you can try response.ops
, for example:
db.collection('mycollection').insertOne(doc, function (error, response) {
if(error) {
console.log('Error occurred while inserting');
// return
} else {
console.log('inserted record', response.ops[0]);
// return
}
});
Official documentation for insertOne
:
http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#insertOne
The callback
type:
http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~insertOneWriteOpCallback
The result
type:
http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~insertOneWriteOpResult
Upvotes: 104
Reputation: 25314
UPDATE 2021: This approach no longer works with the MongoDB driver 4.x. The return of the insertOne only contains an ID and acknowledgement flag
I wanted to still use .then() to resolve by insert so I ended up wrapping the everything in it's own promise.
return new Promise((resolve, reject) => {
db.collection('entries').insertOne({ entry }, (err, res) => {
if (err) {
console.log('error', err);
reject(null);
} else {
resolve(res.ops[0]);
}
});
});
then I could just do
insertEntry({}).then(entry=>{})
Upvotes: 0
Reputation: 2157
Try This
try {
let collection = db.collection('collection_name'); let { ops: inserted } =
await collection.insertOne({ data: object });
// can access array of inserted record like :
console.log(inserted)
} catch (error) {
// log errors
}
Upvotes: 0
Reputation: 422
Posting this as this might be helpful for someone. You can find the updated object like this:
await req.db
.collection('users')
.insertOne({ email, password: hashedPassword, name })
.then(({ ops }) => ops[0]);
Upvotes: 1
Reputation: 2819
The following code worked for me, in MongoDB version 2.2.33.
db.collection("sample_collection").insertOne({
field1: "abcde"
}, (err, result) => {
if(err) console.log(err);
else console.log(result.ops[0].field1)
}
Upvotes: 5
Reputation: 4055
You could use mongojs to do this.
db.collection('mycollection').save(doc, function(error, response){
// response has _id
})
Upvotes: 0
Reputation: 682
You could use mongoose to do this. With the save
method you can insert a document and return it on success. Here is an example from the mongoose documentation:
product.save(function (err, product, numAffected) {
if (err) {
// Handle error...
} else {
// Do something with the returned document...
}
})
Upvotes: 0