I would like to update MongoDb document - javascript

my problem is to update a specific field of the document.
Let's imagine we have multiple input fields when I am just changing one of the field of the document the rest of them going to be null since I am just updating one of them. Is there any simple way to update one field and the rest field not changed.
I can give a switch case or if-else but I do not think it is an
appropriate way to solve this kind issue.
updateChr:async ( args: any) => {
try {
const data = await Client.findByIdAndUpdate(args.clientId,
{$set:
{
chronology:{
status: args.clientInput.status,
note:args.clientInput.note,
date: args.clientInput.date,
file:{
filename:args.clientInput.file.filename,
data:args.clientInput.file.data,
type:args.clientInput.file.type,
size:args.clientInput.file.size,
}
}
},
}
,{useFindAndModify: false})
return transformClient(data);
} catch (err) {
throw err;
}
},

So this part right here is what you need to pay attention to:
{$set:
{
chronology:{
status: args.clientInput.status,
note:args.clientInput.note,
date: args.clientInput.date,
file:{
filename:args.clientInput.file.filename,
data:args.clientInput.file.data,
type:args.clientInput.file.type,
size:args.clientInput.file.size,
}
}
},
}
What you're telling mongo is that, no matter what's in those fields now (or even if they don't currently exist), to set their new values to what you are providing. If you're providing a null value, then it will set its new value to null. If you aren't wanting to update things if their new value is null, then you'll need to clean up your data prior to pushing it to mongo. The easiest way to do this is to sanitize the data prior to adding it to the object you're referencing above. Once you've only got the data that actually exists there, then just loop over the data to create the update object for mongo rather than statically setting it like it is here.
Alternatively, if the data that actually should exist in those fields is available at this stage, you could loop over the null values and fill them in with the current values in mongo or whatever they should be.

Related

Sequelize .update() not using the correct where and updates all rows

I'm trying to create an approval command.
Everything about it, should be working, but it never works correctly.
I've changed my Database to have "id" first, but it still prefers to update on "user" instead.
I've tried having my code just be; but that never worked out. Even though I use it everywhere else.
await ticketApproval.update({status: 1});
I've checked documentation and other StackOverflow questions and answers.
Nothing has worked yet, but from what I can tell, nothing in my code should be telling it to update on the "user" id. Since I only ever tell it to search on the ticket "id" and "server" id
It feels like it's just outright ignoring the Where.
Code
Console
Test Sample
You clearly confuse the update method of a record instance with the static update of a model.
Only static update has the where option because it updates several records in DB using passed conditions in contrast to the instance update method that uses a primary key value of a certain record to update it with passed values.
Compare:
// here we have a model instance for a concrete record
const ticketApproval = await Ticket.findOne({
where: {
id: ticketToApprove
}
})
// by calling the instance `update` we always update this concrete record only
// using a primary key value condition, see a primary key field defined in a model
await ticketApproval.update({ status: 1 });
with
// by calling the static `update` we update all records that satisfy the indicated conditions
await Ticket.update({ status: 1 }, {
where: {
id: ticketToApprove
}
});

How to get and set a ref for a newly cached related object in Apollo client InMemoryCache?

I have a set of related items like so:
book {
id
...
related_entity {
id
...
}
}
which apollo caches as two separate cache objects, where the related_entity field on book is a ref to an EntityNode object. This is fine, the related entity data is also used elsewhere outside of the context of a book so having it separate works, and everything seems well and good and updates as expected...except in the case where the related entity does not exist on the initial fetch (and thus the ref on the book object is null) and I create one later on.
I've tried adding an update function to the useMutation hook that creates the aforementioned related_entity per their documentation: https://www.apollographql.com/docs/react/caching/cache-interaction/#example-adding-an-item-to-a-list like this:
const [mutateEntity, _i] = useMutation(CREATE_OR_UPDATE_ENTITY,{
update(cache, {data}) {
cache.modify({
id: `BookNode:${bookId}`,
fields: {
relatedEntity(_i) {
const newEntityRef = cache.writeFragment({
fragment: gql`
fragment NewEntity on EntityNode {
id
...someOtherAttr
}`,
data: data.entityData
});
return newEntityRef;
}
}
})
}
});
but no matter what I seem to try, newEntityRef is always undefined, even though the new EntityNode is definitely in the cache and can be read just fine using the exact same fragment. I could give up and just force a refetch of the Book object, but the data is already right there.
Am I doing something wrong/is there a better way?
Barring that is there another way to get a ref for a cached object given you have its identifier?
It looks like this is actually an issue with apollo-cache-persist - I removed it and the code above functions as expected per the docs. It also looks like I could instead update to the new version under a different package name apollo3-cache-persist, but I ended up not needing cache persistence anyway.

Updating firestore using previous state

Is it possible to update firestore using the previous state?
So for example I have an address document which has a users field which holds an array of users associated with the address.
whenever I want to add a new user to this array I need the previous array otherwise I will end up overwriting the current data with the new data.
So I end up with something like.
firestore()
.collection("addresses")
.doc(addressId)
.get()
.then(doc => {
this.db
.collection("addresses")
.doc(addressId)
.update({
users: [...doc.data().users, id]
})
});
Is there a way to access the previous data without having to nest calls?
if not
Is there a better way to manage relationships?
If you need the previous value to determine the new value, you should use a transaction. This is the only way to ensure that different clients aren't accidentally overwriting each other's actions.
Unfortunately transactions also need nested calls, since that is the only way to get the current value, and even have one extra wrapper (for the transaction.
var docRef = firestore()
.collection("addresses")
.doc(addressId);
return db.runTransaction(function(transaction) {
// This code may get re-run multiple times if there are conflicts.
return transaction.get(docRef).then(function(doc) {
transaction.update(docRef, { users: [...doc.data().users, id ]});
});
}).then(function() {
console.log("Transaction successfully committed!");
}).catch(function(error) {
console.log("Transaction failed: ", error);
});
The optimal solution is to use a data structure that doesn't require the current value to add new values. This is one of the reasons Firebase recommends against using arrays: they're inherently hard to scale when multiple users may be adding items to the array. If there is no need for maintaining order between the users, I'd recommend using a set-like structure for the users:
users: {
id1: true,
id2: true
}
This is a collection with two users (id1 and id2). The true values are just markers, since you can't have a field without a value.
With this structure, adding a user is as easy as:
firestore()
.collection("addresses")
.doc(addressId)
.update({ "users.id3": true })
Also see the Firestore documentation on
Working with Arrays, Lists, and Sets

Force return all fields including overridden ones

I am running a select query using mongoose. In the schema of the model, it is set to exclude two fields, e.g.:
contents: {
type: String
select: false
},
password: {
type: String
select: false
}
However, when I want to include those fields in exactly one find query, e.g.:
App.findById(_appId)
.exec(err, result){ ... }
without adding a .select statement listing every single field in the model. How do I do that?
I wish I had read the docs more carefully :P. This is possible by adding the following select query to the previous query:
.select('+contents +password');
It still fetched the rest of the model :D
If you've specified select:false on fields, there's no way around having to explicitly override this behavior in your query:
.select('contents password')...
If you don't want this behavior remove the select:false. If you want to retain the bahavior, but find yourself making that query repeatedlly, consider a static method on your model.
schema.statics.materialize = function (appId, cb) {
return this.findById(appId).select('contents password').
exec(cb);
};

Saving a modified document (with a modified subdocument array) in Mongoose model

The code I currently have is:
User.findOne(
{
"subUsers.email" : userEmail
},
{
subUsers : {
$elemMatch: {
email : userEmail }
}
},
function(err, user){
if(user){
var information = user.subUsers[0].information.id(id);
information.arrayA.push({someId : "something"});
user.save(callback(err)); // Also tried information.save()
// without luck
}
callback(err);
}
);
This doesn't return any kind of error, but when I check the DB, the new array element hasn't been pushed (the whole document is intact).
Any help would be much appreciated. Thanks!
You should probably check out the first faq, here: http://mongoosejs.com/docs/faq.html
Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets
notified of the change and so doesn't know to persist the new value. The work-around is to
use [MongooseArray set][1] available in Mongoose >= 3.2.0.
So in your case, you want to add this third line
var information = user.subUsers[0].information.id(id);
information.arrayA.push({someId : "something"});
user.subUsers.set(0, information);
Or something like that.
As of today, Mongoose is currently not prepared for multilevel nesting in an atomic way.
Therefore, even if it's going back to a kind-of relational database, in this case it's better to split the nesting into at least 2 collections, and reference using the automatically generated ObjectId.

Categories