How to change data in a mongoose document with the _id? - javascript

I know this may seem like a generic question but I have done research and it didn't seem to work. I'm making a discord bot and I'm new to this kind of thing. I keep getting this error UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection: Data.users index
This is the code I used:
user.findOneAndUpdate({_id: msg.author, gold: 5});
What is the reason of this problem and how to fix it?

The documentation descibes very clearly what the parameters are:
first parameter: filter
second parameter: update
third parameter: settings object
In our case, you pass a single object, which is interpreted as the filter. You need to pass two objects:
user.findOneAndUpdate({_id: msg.author}, {gold: 5});
This specifies that you want to update gold to 5 for the first record whose _id equals msg.author.
See more examples here: https://mongoosejs.com/docs/tutorials/findoneandupdate.html
Note, that this answer assumes that you have an _id field. If it has a different name, then use that instead.

mongoose .findOneAndUpdate() expects 2 parameters:
the _id of the document you'd update
the new data of the document
So, your code should be this way instead:
user.findOneAndUpdate({ _id: msg.author}, {gold: 5});

Related

How to increment a map value in a Firestore array

I have a firestore firebase database , in which I have a collection users
there is an array in the collection and in the array there is a map
in map there is a field qty.. I want to increment that qty value..
using increment doesnt help as the qty is inside a array index
db.collection("users").doc(checkId).update({
myCart: firebase.firestore.FieldValue.arrayUnion({
qty: firebase.firestore.FieldValue.increment(1),
}),
this is the error Output =>
Uncaught (in promise) FirebaseError: Function FieldValue.arrayUnion() called with invalid data. FieldValue.increment() can only be used with update() and set()
My answer below won't work, given that the qty is in an array. The only way to update an item in an array is to read the entire document, update the item in the array, and then write the entire array with the updated item back to the document.
An alternative would be to use a map instead of an array, and then update the qty using the approach outlined in my (old, and non-working) answer below 👇
You need to specify the full path to the field you're trying to update. So I think in your case, that'll be:
db.collection("users").doc(checkId).update({
"myCart.0.qty": firebase.firestore.FieldValue.increment(1)
}),
The field you want to update is embedded in an array. In this case, you can't use FieldValue.increment(), since it's not possible to call out an array element as a named field value.
What you'll have to do instead is read the entire document, modify the field in memory to contain what you want, and update the field back into the document. Also consider using a transaction for this if you need to update to be atomic.
(If the field wasn't part of an array, you could use FieldValue.increment().)
As of today (29-04-2020)... this is tested by me.
Suppose my data structure is like this:
collection: Users
Any document: say jdfhjksdhfw
It has a map like below
map name: UserPageVisits
map fields: field1,field2,field3 etc
Now we can increment the number field in the map like below:
mapname.field1 etc...
That is use the dot operator to access the fields inside the map just like you would do to an object of javascript.
JAVA Code (Android), update the field using transactions so they can complete atomically.
transaction.update(<documentreference object>,"UserPageVisits.field1",FieldValue.increment(1));
I have just pushed a version of my app which uses this concept and it's working.
Kudos !!
My Best Regards
Previous answers helped me as well, but dont forget about the "merge" property!!! Otherwise it will overwrite your entire array, losing other fields.
var myIndex = 0;
const userRef = db.collection('users').doc(checkId);
return userRef.update({
'myCart.${myIndex}.qty': admin.firestore.FieldValue.increment(1)
}, {
merge: true
});

How to remove a property from document - mongo / loopback

I have an old property on one of my models, and I'd like to remove it from all the documents in a collection. I've tried posting via /upsertWithWhere using the id to update by:
passing in undefined for the value which results in "http error 400 bad request"
passing in null which just sets the property to null
I also was thinking I could do a regular POST and just overwrite each document, but these particular documents are large and I'd rather not do that.
Is there a way to simply patch it?
Edit: Need an answer that implements this Via the Loopback API.
This query should do the trick:
db.collection('collection_name').update({},{$unset: {"old_property": ""}}, {multi:true})
Obviously, just make sure you insert into "old_property" the field name of that old property.
Explaining the query a little further...
"{}" matches all documents in the collection
"{$unset: {"old_property": ""}" removes the field(s) specified
"{multi:true}" (An optional field for update) Allows you to update multiple documents when set to true
Used this as a reference: https://docs.mongodb.com/manual/reference/method/db.collection.update/#multi-parameter

How to increment mongodb fields using variable field name?

So, a little background about what I'm trying to create. I am trying to build a voting app, where a MongoDb database stores the options and the counters for each of those options to check how many times people have voted for each option. The data structure I have implemented looks like below.
_id:"57dfecfa3832360f46e183c2"
options:"iea, aoegboae, aoeugoa, ougr, gege"
options_counter:Object
0:0
1:0
2:0
3:0
4:0
__proto__:Object
title:"hr"
Each of those numbers [0,1,2,3,4] represents an option and the number after the colon represents the counter for each. My function to update the required counter is shown below
var fieldToIncrement = db.collection('polls').options_counter.field;
db.collection('polls').findOneAndUpdate(
{_id: user_id},
{$inc: {fieldToIncrement: 1}},
{upsert:false},
{returnNewDocument: true}
).toArray(function(err, doc){
if(err){
throw new Error(err);
}if(doc){
console.log(doc);
//callback(null, doc);
}
});
However, using the fieldToIncrement variable returns an error saying that cannot find property field of undefined. The variable field contains the number specifying the specific key of the options_counter object that needs to be incremented by 1. I have embedded the options_counter within the original document. My question is how do I set up the syntax so that MongoDb can find the specific key value pair within the options_counter object to update, and increment that counter by 1?
It looks like "options_counter" is a embedded document, for this you var fieldToIncrement has to be something like options_count.0.
I can't see this in your question.
please share your code where you define fieldToIncrement, is now seems undefined as also stated in the error you mentioned: "However, using the fieldToIncrement variable returns an error saying that cannot find property field of undefined."

How can I get the key as well as the value when using db.js to query IndexedDB?

I have an IndexedDB of changes. I add an item like this, and then log the result to check the key has been created successfully:
_this._idb.add('steps', step).done(function (items) {
var item = items[0];
_logger.log("ADDED STEP", { id: item.__id__, step: item }, "CT");
});
The output from this is as expected:
...as you can see, the id has been added to the object when it is stored.
However, when I query the db to getback a list of objects, using this code:
this._idb.steps.query('timestamp').bound(start, end).execute().done(function (results) {
_logger.log("Results", results, "CT");
}
I don't get the id as part of the object that is returned:
... and the lack of id makes updating and deleting impossible.
How can I get the id of the item when I query indexed db using db.js - or am I approaching this in the wrong way, and is there something else I should be doing?
(Note: I'm using TypeScript to compile the JS, but I don't think that's especially relevant to this question)
This is expected behaviour, you're only going to get the __id__ property if you don't define a keyPath in your db schema.
Because there's no keyPath defined the value is not associated with it in indexeddb, it's only added to the resulting object after it has been added, because at that point in time we know the auto-incremented value that IndexedDB has assigned to it.
Since the value isn't really part of the object I don't have any way to assign it to the object when it comes out during a query, maybe I could use the position in the array but that's more likely to be wrong than right.
If you want the ID to be persisted against the object then you need to define a keyPath as part of the object store schema and the property will be added to the resulting object and available and it will be on the object returned from a query.
Disclaimer - I wrote db.js
Looking at the source, __id__ is only defined when your keyPath is null in the add() method. From what I'm seeing, you'll never see this in a query() response.
In IDB null keyPaths are allowed only when using auto-incrementing ("out-of-line") keys. So if you're getting the object back, it should have an auto-incrementing key on it or some other keyPath.
The __ prefix in JavaScript usually means the developer intended it to be a "private" property. I'm guessing this is for internal use and you shouldn't be counting on this in your application code.
Consider using explicit, so-called "in-line" keys on your object store.
The goal of db.js is easy and simple to use. Your is advanced use case.

Updating a subfield in a mongoDB document using findOne and save

I'm trying to update a particular subfield in a mongoDB document and have decided to first find the object in question and then save an updated one. For some reason, the save option seems to ignore my changes.
I have one object in my collection, and it meets the following schema:
var tschema= mongoose.Schema({
a: Object
})
var t = db.model('tongoose',tschema);
t.findOne({},function(err,obj){
console.log(obj.a); //yields ['banana',3]
obj.a[1]=1; //to make ['banana',1]
console.log(obj); //yields ['banana',1]
obj.save(function(err,real){
console.log(real); //yields ['banana',1]
});
});
But when I go back to the mongoDB and look up the saved object, it never shows any changes. Can you spot what I'm doing wrong?
Much appreciated.
Because your schema defines a as a generic object, that field is treated as the Mixed type by Mongoose and you need to mark it as changed by calling markModified or save will ignore the change.
obj.markModified('a');
obj.save(function(err,real){ ...
See the discussion of Mixed types on this page of the docs.

Categories

Resources