Mongo update removing other keys in document - javascript

I am trying mongo update where one document key from a different collection is inserted into another collection.
CODE
// update user document with remove of otp and new state set.
updateOne = await db.collection(_collection).updateOne(
// search basis.
__docUpdateSearchBasis,
// updates.
__docUpdateBasis
)
RESULT

You need to make query like this:
updateOne = await db.collection(_collection).findOneAndUpdate(
//Condition
{
_id: req.user.id
},
//Update what you want
{
$set: {
key: value
}
});

Related

Mongoose search by array entries ($in) behavior not aligned with MongoDB Atlas

I'm running a Node.js server, connecting to a MongoDB database with mongoose.
Inside my controller, I have several methods that make operations to the database. One of them is this one:
async findMultiple(req, res) {
const [baseSkillsArray] = Array(req.body);
try {
// if there is not baseSkillsArray, skip
if (!baseSkillsArray) {
return res.status(200).send([]);
}
// find all baseSkills using the ids in the baseSkillsArray
const allBaseSkills = await BaseSkill.find({
_id: { $in: [baseSkillsArray.baseSkillArray] } //
});
console.log('test ' + allBaseSkills);
res.status(200).send(allBaseSkills);
} catch (error) {
console.error(error.message);
res.status(500).send('Server error find BaseSkills');
}
}
However, this returns me nothing. I did some debugging and I found the reason is the find id $in the array. So I tried hard coding a value, like '2', for instance.
// find all baseSkills using the ids in the baseSkillsArray
const allBaseSkills = await BaseSkill.find({ _id: { $in: ['2'] } });
No success. So I went to MongoDB Atlas, where my DB is stored. I tried filtering using the same line of code in my collections.
{ _id: { $in: ['2'] } }
Surprisingly, it returns my document as I wanted!
The issue is that I need to make it work with mongoose. Any ideas? Is this a known bug?
There is nothing wrong with the query, nor a bug regarding $in.
In fact, what's wrong is the actual collection name. I manually created a collection in MongoDB Atlas, called "baseSkills". However, mongoose by default transforms your collection name into lowercase and adds an "s" if your collection's name is not in the plural.
So every time I started my server, I noticed that there was a new collection called "baseskills". I assumed it was a bug and deleted it. Only after making this post that I realized the collection was there again.
So I exported the documents to this collection and my query was working fine.
FYI, there is a way to enforce the collection's name in mongoose. When you declare you model, add a second parameter to the Schema function called "collection". Here is an example:
const BaseSkillSchema = new mongoose.Schema({
_id: {
type: String,
required: true
}, ...
}, { collection: 'baseSkills' })
That's it! Sorry for the mess and thank you for your help!
you want to query over mongo db object ids. So you should create a new ObjectId to do that.
import {Types} from 'mongoose';
{ _id: { $in: [new Types.Object("2")] } }
Or if you have 2 ids one generated and one custom created as id then you can query without creating a new object.
{ id: { $in: ['2'] } }

Realtime database update or create functionality

I have a user object in firebases realtime database. I am querying realtime database and when successful I am wanting to write some new data to the user object under the users node.
My desired outcome: When a user has not fetched the information before, a new field called 'lastViewed' under the user object is created and if the field has already been created then we update the timeViewed keys value. A user can have multiple objects in the array corresponding to the uuid of the fetched data.
Please see the user object below
This may not need to be an array if using .push()
-N0X8VLHTw3xgvD2vJs- : { // this is the users unique key
name: 'myName',
lastViewed: {
[
{
timeViewed: 1651558791, // this is the field to update if exists
datasUniqueKey: 'N17ZmwIsbqaVSGh93Q0' // if this value exists update timeViewed else we create the entry.
},
{
timeViewed: 1651558952,
datasUniqueKey: 'N17ZmwIsbqaVSad3gad'
},
]
}
}
Please see my attempt below.
const getData = database()
.ref(`data/${uniqueKeyFromData}`)
.on('value', snapshot => {
if (snapshot.exists()) {
database()
.ref(`users/${currentFirebaseUserKey}/lastViewed`) // currentFirebaseUserKey = N0X8VLHTw3xgvD2vJs
.once('value', childSnapshot => {
if (childSnapshot.exists()) {
// update
database()
.ref(
`users/${currentFirebaseUserKey}/lastViewed`,
)
.update({
timeViewed: new Date(), // new data will not give us the corresponding date format in the user object above but don't worry about that
fetchedDatasUniqueKey: uniqueKeyFromData,
});
} else {
// create
database()
.ref(
`users/${currentFirebaseUserKey}/lastViewed`,
)
// Push creates a unique key which might not be required so maybe set?
.push({
timeViewed: new Date(),
fetchedDatasUniqueKey: uniqueKeyFromData,
});
}
});
}
});
Where I think I am going wrong
Above I am not creating an array, if I use push I would get a unique key generated from firebase but then would have to use that key when updating, something like
`users/${currentFirebaseUserKey}/lastViewed/${lastViewedUniqueKey}`
So the user object would look like so
-N0X8VLHTw3xgvD2vJs- : { // this is the users unique key
name: 'myName',
lastViewed: {
-N17i2X2-rKYXywbJGmQ: { // this is lastViewedUniqueKey
timeViewed: 1651558791,
datasUniqueKey: 'N17ZmwIsbqaVSGh93Q0'
},
}
}
then check for snapshot.key in the if?, any help would be appreciated.
Since you don't want a list of data, but a single set of properties for ``, you should just call set instead of push:
database()
.ref(`users/${currentFirebaseUserKey}/lastViewed`)
.set({ // 👈
timeViewed: new Date(),
fetchedDatasUniqueKey: uniqueKeyFromData,
});
I also don't think you need the two different cases here for create vs update, as both seem to do the exact same thing. If you do need both cases though, consider using a transaction.

Sequelize user.increment("somethings") do not update the value

when I try to increment something with sequelize it doesn't return me the updated value (incremented) and to get that I need to reuse findOne method.
Looking in the sequelize doc here in the increment section you can read this:
The updated instance will be returned by default in Postgres. However,
in other dialects, you will need to do a reload to get the new values.
Is ther any way to "fix" it without using this "workaround" ( recalling findOne )?
const user = await Tags.findOne({
where: { id: ID },
});
await user.increment("rank");
const user1 = await Tags.findOne({
where: { id: ID },
});

How to append nodejs sequelize model list of json field

How to append a list of JSON filed in nodejs Sequelize
database: Postgres
I have one model field like that :
student_list:
{
type: Sequelize.ARRAY(Sequelize.JSON),
allowNull: true
},
I am trying to append Sequelize Array of JSON like this way but not get sucessfully append list:
var data = ({'share_by':"aaa",'list_name':"list_name"})
student.update(
{'student_list': Sequelize.fn('array_append', Sequelize.col('student_list'), data)},
{'where': {studet_id: student_id}}
);
how to do this?
You can do a find() and get the element value, update the element and do a update with data updated. Like this:
// Get the actual student data
const student = await student.findOne(studentId);
// Spread and add the new value
const student_list = {
...student_list,
data
};
// Update the field
await student.update(
{
student_list
},
{
where: {
student_id
}
}
);

document wont save using save() method with mongoose

I have this schema:
var UserSchema = mongoose.Schema({
analytic: {
type: Object,
default: {
today:[],
weekly:[],
monthly:[],
yearly:[],
allTime:[]
}
}
});
let User = mongoose.model("bloger", UserSchema);
module.exports = {User};
and I am trying to save some data into one of the arrays like so:
User.findOne({username:username}, (e, user) => {
if (e) {
res.send('error fetching post')
}
else if (!user) {
res.send('no user found')
}
else if (user) {
user.analytic.today.push(req.body.visitor) // push the data object to the array
user.save((e, doc) => {
if (e) {
res.send(e)
}
if (doc) {
console.log('user saved')
res.send(doc)
}
})
}
})
})
I am getting the doc object on save() and not the e so I though it should have save it but it wasn't.
I have had a similar issue before this is because I am not defining a new Model I am just passing a JSON object.
Instead of saving the object you need to create a new model and save that.
Try creating a new model passing the save into it like below;
var newUser = new User(user);
newUser.save((e, doc) {
if (e) {
res.send(e)
}
if (doc) {
console.log('user saved')
res.send(doc)
}
});
Making sure you require the User Model inside the script.
Performing deep modifications in objects not in your schema makes Mongoose oblivious to those changes, preventing it from knowing what to save (and from making efficient atomic updates). The end result is that, when calling .save, Mongoose thinks there's nothing modified and therefore does nothing.
In your particular scenario, you have two options:
1. Add your analytics sub-arrays to your schema
This is the best option and allows for finer control of everything:
const UserSchema mongoose.Schema({
analytic: {
today: [{}],
weekly: [{}],
monthly: [{}],
yearly: [{}],
allTime: [{}],
}
});
With this, those arrays are now known to Mongoose and everything should work correctly.
Note that you don't need defaults in this case, as Mongoose is smart enough to create the arrays as needed.
2. Manually mark modified object as modified
If for any reason you don't want or can't modify the schema, you can manually mark the analytic object as modifies so Mongoose knows of it:
user.analytic.today.push(req.body.visitor) // push the data object to the array
user.markModified('analytic'); // mark field as modified
user.save(...);
This signals Mongoose that analytic or any of its children have changed and triggers an update when calling .save. Note however that Mongoose views this as a full change in the object, while with option 1 it can use $push instead.

Categories