insert many don’t working in mongo DB why? - javascript

I am trying to insert many in mongoDB using mongoose’s .it only save one collection only why
Here is my code
https://codesandbox.io/s/gallant-solomon-o91wp
I save like that
app.get("/saveData", async () => {
try {
const data = [
{
empid: "test123",
date: "19-Jul-2019"
},
{
empid: "test13",
date: "18-Jul-2019"
},
{
empid: "test13",
date: "11-Jul-2019"
}
];
console.log("before save");
let saveBlog = await BlogPostModel.collection.insertMany(data, {
checkKeys: false
}); //when fail its goes to catch
console.log(saveBlog); //when success it print.
console.log("saveBlog save");
} catch (error) {
console.log(error);
}
});
try to fetch data like that
app.get("/filter", async (req, res) => {
try {
let filterBlog = await BlogPostModel.find({});
//when fail its goes to catch
console.log(filterBlog); //when success it print.
res.send(filterBlog);
} catch (error) {
console.log(error);
}
});
showing only one document

So, here as i suspected, there is one more index present in the collection you created i.e blogposts. the index is id [key id name id_1].
Here is your whole project, i have added in glitch.
Demo
and here i also have added one api /indexes , this retrieves all indexes of the collection. by default _id should be there, additional indexes are added after. so here you can see id, which needs to be unique.
i have made few more changes to your code.
The route /saveData now able to insert records. and it has the field called id which is unique.
but, the old route that is now at /saveData_old, which will give you error as there are no keys that represents this index key [id]. [also after inserting one, it will have id null and rest will fail, just causing duplicate ]
now you can either use id key with unique values, or if you don't need you can also drop the index as well. you can find an answer here for how to drop index.

Related

Unable to delete element from array of objects using mongoose

I am trying to remove one element from array of objects in MongoDB.
Please find the schema structure below.
I just want to remove one object by status, ideaID and invitedBy. Please find the query I am using for it,
await User.findByIdAndUpdate(
currentUser,
{ $pull: { "invitationStatus.ideaId": this.req.body.ideaId, "invitationStatus.status": "pending", "invitationStatus.invitedBy": getUserByNotificationId.createdBy._id } })
but this query is not removing the specified object.
You have to specify from which field you want to pull item. Change your query like this:
await User.findByIdAndUpdate(currentUser, {
$pull: {
invitationStatus: {
ideaId: this.req.body.ideaId,
status: "pending",
invitedBy: getUserByNotificationId.createdBy._id
}
}
})

Get the _id of the created element instead of the whole data in mongodb

I have a problem accessing the _id of the last created element inserted in to mongodbe.
is there any solution to just get the id, instead of getting all elements? especially if the data list is so long and nested so its really hard to pin the created element and gain access to his id
I am using mongoose driver on this one.
let updateDeptArr = await Budget.findOneAndUpdate(
// Dynamic
{
'_id': `${propertyValues[0]}`, // user ID
[`${keys[2]}._id`]: `${propertyValues[1]}`
},
{
'$push': {
[`${keys[2]}.$.${keys[3]}`]: propertyValues[3]
}
}, { _id: true, new: true }
).then(function (data) {
// we need to get and send The id of the last created element!!!
console.log(data[keys[2]]);
// let order = data[keys[1]].length - 1
// let id = data[keys[1]][`${order}`]._id
// res.json({ _id: id })
})
}
You can use select after query.
In the upcoming listing, you have a mongoose schema being used to query MongoDB, and just two fields are selected, as you want.
Loc
.findById(req.params.locationid)
.select('name reviews')//select chained
.exec();
Try to chain select to your call. It will just give back the name and reviews.
Try this:
let updateDeptArr = await Budget.findOneAndUpdate(
// Dynamic
{
'_id': `${propertyValues[0]}`, // user ID
[`${keys[2]}._id`]: `${propertyValues[1]}`
},
{
'$push': {
[`${keys[2]}.$.${keys[3]}`]: propertyValues[3]
}
}, { _id: true, new: true }
).select("_id")// not sure if Mongoose will chain this way
.then(function (data) {
// we need to get and send The id of the last created element!!!
console.log(data[keys[2]]);
// let order = data[keys[1]].length - 1
// let id = data[keys[1]][`${order}`]._id
// res.json({ _id: id })
})
}

Returning updated object after update to database instead of count

I am making an update to an entry in a database of food trucks. This is what my model looks like for this particulate update:
function editTruck(changes, id) {
return db('trucks')
.where({ id })
.update(changes)
.then(id => {
return findTruckById(id);
})
}
I want to return the actual updated entry in object form. As you can see above, I tried to accomplish this by drawing on another method in the model called findTruckById. This is what findTruckById looks like:
function findTruckById(id) {
return db('trucks')
.select('id', 'name', 'image', 'operator_id', 'cuisine_type', 'physical_address')
.where({ id })
.first()
}
This doesn't work because the response returned from the editTruck method is just a count of the entries in the database that were updated, which is 1, as opposed to an id or an array of ids for the entries. Therefore, it always just returns 1 and running 1 inside findTruckById returns an object equivalent to the entry in the trucks database with id 1, which is definitely not what we want. How can I solve this problem?
You already have the ID, you don't need the "update" to return it.
function editTruck(changes, id) {
return db('trucks')
.where({ id })
.update(changes)
.then(() => { // you already have the id, just use the `id` that is already in the scope
return findTruckById(id);
})
}

How to update Array field?

Im using Firebase Firestore and want to update an array field under a userprofile with the latest chat thread's id.. Im guessing that I have to pull the entire array (if it exists) from the chat node under that user, then I need to append the new id (if it doesnt exist) and update the array.. It works when theres only 1 value in the array then it fails after that with the following error:
Transaction failed: { Error: Cannot convert an array value in an array value.
at /user_code/node_modules/firebase-admin/node_modules/grpc/src/node/src/client.js:554:15 code: 3, metadata: Metadata { _internal_repr: {} } }
and here is my firebase cloud function, can anyone tell me where im going wrong ?
exports.updateMessages = functions.firestore.document('messages/{messageId}/conversation/{msgkey}').onCreate( (event) => {
/// console.log('function started');
const messagePayload = event.data.data();
const userA = messagePayload.userA;
const userB = messagePayload.userB;
// console.log("userA " + userA);
// console.log("userB " + userB);
// console.log("messagePayload " + JSON.stringify(messagePayload, null, 2) );
const sfDocRef = admin.firestore().doc(`users/${userB}`);
return admin.firestore().runTransaction( (transaction) => {
return transaction.get(sfDocRef).then( (sfDoc) => {
const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);
transaction.update(sfDocRef, { chats: array } );
});
}).then( () => {
console.log("Transaction successfully committed!");
}).catch( (error) => {
console.log("Transaction failed: ", error);
});
});
You're nesting arrays in your code here:
const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);
This leads to an array with two values, the first one being the new messageId and the second value contains an array all of your previous values, e.g.
[ "new message id", ["previous id", "older id"] ]
This type of nested array is something that Firestore (apparently) doesn't allow to be stored.
The solution is simple:
const array = [event.params.messageId, ...sfDoc.get('chats')];
The fact that you have to first load the array to then add a single element to it is one of reasons Firebasers recommend not storing data in arrays. Your current data looks like it'd be better off as a set, as shown in the Firestore documenation:
{
"new message id": true,
"previous id": true,
"older id": true
}
That way adding a chat ID is as simple as:
sfDocRef.update({ "chats."+event.params.messageId, true })
I have looked further into the matter, and I would follow the advice that Frank gave you in his post; allocate the data in collections rather than with arrays as they have greater versatility for Firebase 1. Researching under the examples listed in the Firebase website looking for anything related to a chat, I’ve found the data structure and code for messages that are used by Firechat as they might be of use for you.
In the source code, they use a collection for the their message-id -userId pair with the following topology 2 :
The exact way how the saving is executed at the repository is 3 :
It executes an append of the message into the Room-id collection. Instead of this structure, you could use an userID - messageID pair as it might fit you better.

mongoose search for userid inside an array and if found, delete it along with duplicates. how?

So someone hits the like button. It'll call this function below. I need it to not push the same user twice. Also if the like button is pressed again it'll act as a dislike or remove like, so it should delete the user from this array of likes. How do I do that? This is what I have so far
chapterController.likeChapter = function (req, res) {
var userId = req.body.by;
var chapterId = req.body.chapterId;
Chapter.findOne({
_id: chapterId
}, function(err, chap){
if(chap.likes.indexOf(userId) !== -1){
chap.likes.pull(userId);
}else{
chap.likes.addToSet(userId);
}
chap.save();
})
Chapter.findByIdAndUpdate(chapterId, {
$push: {
likes: userId
}
}, {}, function(err, obj) {
if (err) {
console.log(err);
} else {
Chapter.find({_id: chapterId}).then(function (chapter) {
var chapter = chapter;
Comment.find({chapterId: chapterId}).then(function(data){
return res.send({ commentList : data, user: req.user, chapter: chapter});
//console.log(chapter);
});
})
}
});
};
UPDATE: it does most of what I want so far with what I have posted. I need it to delete all duplicates as well. Not just one.
I dont exactly know your data model but inside the callback of Chapter.findByIdAndUpdate you can map the user id's like this;
obj.userid.map((userIdFromDb) => {
if(userIdFromDb !== userId) {
do something...
}
})
But i higly suggest you that, if you have any growing data by time, do not use mongodb. You can use relational database and mongo would hold for you statics in this case.
I need it to not push the same user twice.
Use $addToSet instead of $push.
Chapter.findByIdAndUpdate(chapterId, {
$addToSet: {
likes: userId
}
}, ...
Also if the like button is pressed again it'll act as a dislike or remove like, so it should delete the user from this array of likes.
Use the $pull operator in an update like the one you have for the $push case:
Chapter.findByIdAndUpdate(chapterId, {
$pull: {
likes: userId
}
} ...

Categories

Resources