Mongodb duplicate errorr - node.js

db.collection("resource").update({name: name}, {
name: name,
type: type
}, {
upsert: true
}
I differentiate documents by their names. I do not add document if it exists with the same. But I want to warn user by saying "It already exists, operation failed" How can I achieve it?

It sounds like you want to insert documents, not update or insert documents.
1: Add unique index on resource.name ahead of time.
db.resouces.createIndex({ name: 1 }, { unique: true })
Important: do this once, not on every request.
See mongodb create index docs.
2: Use insert instead of update + upsert.
It sounds like you want to actually insert a document, and get an error if there is a duplicate key.
db.resources.insert({ name: "AJ" }) // ok
db.resources.insert({ name: "AJ" }) // error!
You will get a duplicate key error on the second insert. Error code 11000.
See mongodb docs on insert.
3: Use promise-try-catch in javascript.
The code to do error checking looks like:
var db = require("mongojs")(DATABASE_URL, [ "resources" ])
var duplicateKey = function (err) {
return err.code == "11000"
}
db.resources.insert({ name: name })
.then(function () {
// success!
})
.catch(duplicateKey, function () {
// sorry! name is taken
})

Related

I get a "($) prefixed field '$numberDecimal' in 'price.$numberDecimal' is not valid for storage." error when trying to update a field on my back-end

lately I've been trying to update a price field in my mongodb database but I'm facing an annoying issue.
The collection I'm trying to modify is listingsandReviews, within the database sample_airbnb.
The field in question is made as such price {$numberDecimal: priceVar}.
On my back end (using Express.js DAO architecture), my update query looks as such:
// console.log(roomContent.amenities)
let price = roomContent.price.$numberDecimal
try {
const roomIdResponse = await rooms.updateOne(
{ _id: roomId },
{ $set: {
name: roomContent.name,
address: {street: roomContent.address.street},
price: {'$numberDecimal': price},
property_type: roomContent.property_type,
bedrooms: roomContent.bedrooms,
beds: roomContent.beds,
minimum_nights: roomContent.minimum_nights,
maximum_nights: roomContent.maximum_nights,
amenities: roomContent.amenities,
description: roomContent.description
}
},
{ upsert: true }
);
return roomIdResponse;
}
catch (e) {
console.error(`Unable to update room: ${e}`);
return { error: e };
}
}
the shell gives me back that error Unable to update room: MongoServerError: The dollar ($) prefixed field '$numberDecimal' in 'price.$numberDecimal' is not valid for storage.
I've been looking at every resource possible, some saying I should try NumberDecimal(), others decimal128, but nothing works so far.
You could say I could fix the issue on the front-end, but that wouldn't make the database structure consistent, which I want to avoid.

How to update the childs value of an object present in the mongod using mongoose with node.js?

i want to update particular child's value which is actually present inside the object and wants all my rest value be the same.
i want to use mongoose npm package.
for example:
basic:{
name: "ABC",
mobile: 1234567890,
age: 20
},
other:{
pincode: 123456,
email: "abc#abc.com"
}
My Code
Model.findOneAndUpdate(
{ "basic.mobile": 1234567890 },
{
basic:{ name: "CDE"}
},
(err, doc) => {
if (err) return res.send({ error: err });
res.send(`updated`);
}
);
it works but it override the previous basic data and create a new one which i provided. it should update but also rest value should be there.
how can i do this?
Your question contains the answer. For Filter you are referring a single field using dot operator properly that is
"basic.mobile": 1234567890
You should do similar thing for update as well, that is the second argument of your function call, the way you have defined is wrong becuase it is a new object - that should be used when you want replace whole basic object in DB. If you want to just update the name field then you should use dot operator like below.
"basic.name":"CDE"
So the whole function would look like below.
Model.findOneAndUpdate(
{ "basic.mobile": 1234567890 },
{ "basic.name": "CDE"},
(err, doc) => {
if (err) return res.send({ error: err });
res.send(`updated`);
}
);

Mongodb upsert command in nodejs

I have created a collection named Account.
At first shot, I am inserting around 5 records.
{"Id":"0012800000C6Q19AAF","Name":"Aditya Kumar"}
{"Id":"0012800000C6MldAAF","Name":"GenePoint"}
{"Id":"0012800000C6MlbAAF","Name":"United Oil & Gas, UK"}
{"Id":"0012800000C6MlcAAF","Name":"United Oil & Gas, Singapore"}
{"Id":"0012800000C6MlTAAV","Name":"Edge Communications"}
{"Id":"0012800000C6MlUAAV","Name":"Burlington Textiles Corp of America"}
I am bringing data from the external system, which has already an ID field associated with it.
Again next time when a request comes for inserting extra 5 records, I want to check if Id field of upcoming records already exists in my MongoDB(if yes, then do an update else insert).
And don't get confused by Id field coming from external system with _Id field created for every MongoDB document.
Here is what I have tried:
var x= fields["data"]; obj='Account';
db.createCollection(obj);
db.collection(obj).insert(fields, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new contact.");
} else {
res.status(201).json(doc.ops[0]);
}
})
Use the updateOne method:
db.collection.updateOne(
{ _id: id },
{ $set: { name: 'name' } },
{ upsert: true }
);
If a record with the matching id is found then the name field will be updated, otherwise a new record will be created.

MongoDB, Updates and Controlling Document Expiration

I'm working on a node.js project. I'm trying to understand how MongoDB works. I'm obtaining data hourly via a cron file. I'd like for there to be unique data, so I'm using update instead of insert. That works fine. I'd like to add the option that the data expires after three days. Its not clear to me how to do that.
In pseudo code:
Setup Vars, URL's, a couple of global variables, lineNr=1, end_index=# including databaseUrl.
MongoClient.connect(databaseUrl, function(err, db) {
assert.equal(null, err, "Database Connection Troubles: " + err);
**** db.collection('XYZ_Collection').createIndex({"createdAt": 1},
{expireAfterSeconds: 120}, function() {}); **** (update)
s = fs.createReadStream(text_file_directory + 'master_index.txt')
.pipe(es.split())
.pipe(es.mapSync(function(line) {
s.pause(); // pause the readstream
lineNr += 1;
getContentFunction(line, s);
if (lineNr > end_index) {
s.end();
}
})
.on('error', function() {
console.log('Error while reading file.');
})
.on('end', function() {
console.log('All done!');
})
);
function getContentFunction(line, stream){
(get content, format it, store it as flat JSON CleanedUpContent)
var go = InsertContentToDB(db, CleanedUpContent, function() {
stream.resume();
});
}
function InsertContentToDB(db, data, callback)
(expiration TTL code if placed here generates errors too..)
db.collection('XYZ_collection').update({
'ABC': data.abc,
'DEF': data.def)
}, {
"createdAt": new Date(),
'ABC': data.abc,
'DEF': data.def,
'Content': data.blah_blah
}, {
upsert: true
},
function(err, results) {
assert.equal(null, err, "MongoDB Troubles: " + err);
callback();
});
}
So the db.collection('').update() with two fields forms a compound index to ensure the data is unique. upsert = true allows for insertion or updates as appropriate. My data varies greatly. Some content is unique, other content is an update of prior submission. I think I have this unique insert or update function working correctly. Info from... and here
What I'd really like to add is an automatic expiration to the documents within the collection. I see lots of content, but I'm at a loss as to how to implement it.
If I try
db.collection('XYZ_collection')
.ensureIndex( { "createdAt": 1 },
{ expireAfterSeconds: 259200 } ); // three days
Error
/opt/rh/nodejs010/root/usr/lib/node_modules/mongodb/lib/mongodb/mongo_client.js:390
throw err
^
Error: Cannot use a writeConcern without a provided callback
at Db.ensureIndex (/opt/rh/nodejs010/root/usr/lib/node_modules/mongodb/lib/mongodb/db.js:1237:11)
at Collection.ensureIndex (/opt/rh/nodejs010/root/usr/lib/node_modules/mongodb/lib/mongodb/collection.js:1037:11)
at tempPrice (/var/lib/openshift/56d567467628e1717b000023/app-root/runtime/repo/get_options_prices.js:57:37)
at /opt/rh/nodejs010/root/usr/lib/node_modules/mongodb/lib/mongodb/mongo_client.js:387:15
at process._tickCallback (node.js:442:13)
If I try to use createIndex I get this error...
`TypeError: Cannot call method 'createIndex' of undefined`
Note the database is totally empty, via db.XYZ_collection.drop() So yeah, I'm new to the Mongo stuff. Anybody understand what I need to do? One note, I'm very confused by something I read: in regards to you can't create TTL index if indexed field is already in use by another index. I think I'm okay, but its not clear to me.
There are some restrictions on choosing TTL Index: you can't create
TTL index if indexed field is already used in another index. index
can't have multiple fields. indexed field should be a Date bson type
As always, many thanks for your help.
Update: I've added the createIndex code above. With an empty callback, it runs without error, but the TTL system fails to remove entries at all, sigh.

MongoDB Upsert add to array

I'm trying to insert/update an array of strings in a mongodb document using some typescript code running in NodeJS.
The following code is typescript but I guess JS developers will get it w/o any problems:
export function addEvents(entityId: string,
events: string[] ,
callback: () => void) {
db.collection('events', function(error, eventCollection) {
if(error) {
console.error(error); return;
}
eventCollection.update({ _id: entityId }, { "$pushAll ":
{ events: events }},
function(error, result) {
if(error) {
console.error(error); return;
}
callback();
});
});
}
the document have the following structure:
{
_id : string
events : ["array","of","strings"]
}
I simply want to append an array strings at the end of the existing array for a specific _id.
I don't quite get if I should use update,save, $push ,$pushall etc.
Can someone explain?
If I understood correctly the problem is that pushAll does nothing or update returns error? Maybe copy-paste mistake in your example but I think you have typo here.
{ "$pushAll ": { events: events }}
It should be
{ $pushAll: { events: events }}
Your combination of update and $pushAll looks like the best choice for what you're doing here -- it's for appending an array to an existing array. $push is for adding an element to an array. save would involve getting the existing events array, appending to it, then saving the document.
The extra space in "$pushAll " needs to be removed. It may have quotes: "$pushAll".
Found the problem, I needed to pass "{ upsert = true }" as a third argument to the update function.
To achieve 'upsert' semantics in this case, you'd need to use $addToSet. If you have an array of values to add, you'd need to throw in the $each modifier. From mongo shell:
db.events.update(
{ _id: entityId },
{ $addToSet: { $each: events } }
)

Resources