Mongoose: How to push in nested array? [duplicate] - node.js

This question already has answers here:
Updating a Nested Array with MongoDB
(2 answers)
Closed 3 years ago.
I am very new to NoSQL world. Here the screenshot of my Mongoose schema.
I need to insert,update and delete document to/from vehicles array.
What I have tried so far:
Add: (Working)
Companies.findOne({'mobile' : givenMobileNumber, 'VehicleGroups.vehicle_group_id' : vehicleGroupId}, (err, res) => {
if( err || res == null) {
callback(err, res);
}else{
var len = res.VehicleGroups.length;
for(var i=0; i<len; i++)
{
if(res.VehicleGroups[i].vehicle_group_id == vehicleGroupId)
res.VehicleGroups[i].vehicles.push(data);
}
res.save(callback);
}
})
Delete: (Working)
Companies.findOneAndUpdate({ mobile : givenMobileNumber, 'VehicleGroups.vehicle_group_id' : vehicleGroupId},
{ $pull : {'VehicleGroups.$.vehicles' : { 'vehicle_id' : vehicleId} } }, callback);
Still working to update data. Is my approach valid?
Thanks

You can consider setting up separate schemas for your VehicleGroups and vehicles and reference them through ObjectId in your Companies schema:
VehicleGroups: [{
_id: { type: Schema.Types.ObjectId, ref: 'vehicleGroup' },
// All other properties here
vehicles: [{ type: Schema.Types.ObjectId, ref: 'vehicle' }]
}]
Adding a new document to theVehicleGroup schema would then go something like this:
const newVehicleGroup = new VehicleGroup({
name: 'New Vehicle',
// Set all other fields
})
And adding it to the Companies schema:
Companies.findOneAndUpdate({
mobile : givenMobileNumber, 'VehicleGroups.vehicle_group_id' : vehicleGroupId,
{ $push: { vehicleGroups: newVehicleGroup._id } }
})
Since you reference vehicles and VehicleGroups by ObjectId, all you have to do to update that reference is to update the document in the respective collection.
However, if you delete a document you will need to remove its reference from the respective array in the Companies collection.
See if this approach makes it a little easier!

Related

Get table A values with table B where A.field_name = B.field_name [duplicate]

This question already has answers here:
How do I perform the SQL Join equivalent in MongoDB?
(19 answers)
Closed 3 years ago.
In back end I'm using mongoose, express and node js. I want to do joins in mongodb. If this is SQL it's not hard. Since I'm new to mongo database. This is problem to me. I already tried many answers in this platform and none of them help my situation.
I have following two schema in my database.
Item
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
export const item_schema = new Schema({
item_no: {
type: String
},
name: {
type: String
},
item_category: {
type: String
},
no_of_copies: {
type: Number
},
public_or_rare: {
type: String
},
user_no: {
type: String
}
});
Book
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
export const book_schema = new Schema({
item_no: {
type: String
},
isbn_no: {
type: String
},
author: {
type: String
},
published_year: {
type: Number
},
publisher: {
type: String
},
book_category: {
type: String
}
});
Note that there is no error in these models because those runs well with other controllers in my API
I want to get book and item tables data as one object where book and item share same item_no
In order to achieve my aim so far I tried following code,
export const get_books_all_details = (req, res) => {
Book.find({}, (err, book) => {
if (err) {
res.send(err);
}
else {
let my_book = book;
// res.json(my_book);
Item.findOne({ item_no: my_book.item_no }, (err, item) => {
//Item.find({}, (err, item) => {
if (err) {
res.send(err);
}
else {
let my_item = item;
//res.send(my_book+my_item);
res.json({
/* item_no: my_item.item_no,
item_name: my_item.item_name,
item_category: my_item.item_category,
no_of_copies: my_item.no_of_copies,
public_or_rare: my_item.public_or_rare,
isbn_no: my_book.isbn_no,
author: my_book.author,
published_year: my_book.published_year,
publisher: my_book.publisher,
book_category: my_book.book_category , */
book:my_book,
item:my_item
})
}
});
}
});
};
In top I use find() to get all books and if there is record in item table which matches item_no I want to get that particular item too. That's why I used findOne() inside find()
I don't know is it right or wrong !
So this new guy wait for you guys help and really appreciate it. If you could help me with code and explanations that will be great !
I want to do joins in mongodb
Just don't. MongoDB is a NoSQL database, specifically built to avoid joins and to enforce denormalization of data. If you need to join a document, put it inside of another document. If you build your collections in MongoDB like you do in any SQL database, you'd just have a non ACID compliant relational database, which is dangerous.

Issue in saving values in array in mongoose model using save() [duplicate]

This question already has answers here:
Push items into mongo array via mongoose
(11 answers)
Closed 5 years ago.
I am trying to update a document in a collection. I am particularly trying to update an array of Strings.The following is my Schema
var sampleSchema= mongoose.Schema({
fullName : String,
email : String,
rolesTaken : [String],
});
I basically have an array of such schema's. I want to update the rolesTaken array for all of them.
So I did the following
var async = require('async');
var ATmapping = require('path to Schema');
ATmapping.find({},function(err,lists){
if(err){
console.log(err);
return;
}
if(lists.length > 0){
async.each(lists,function(list,callback){
if(!list.rolesTaken){
list.rolesTaken =[];
}
list.rolesTaken.push("Patient");
list.markModified('rolesTaken');
list.save(function(err,item){
if (err){
console.log(err);
}
console.log('Saved', item);
callback();
});
});
}
});
I have browsed a lot and the most popular solution was to add markModified. But it doesn't seem to work in my case.When I added mongoose.debug i got the following
atmappings.update({ _id: ObjectId("59074b127adeef0004b84ac3"), __v: 7 }, { '$set': { rolesTaken: [] }, '$inc': { __v: 1 } })
As you can see the roles taken is empty despite me adding markmodified and save(). I would like to know if I am missing something which is preventing me from saving the values in the schema.
Thanks in advance.
Here is how I push a comment to a thread in one of my apps using mongoose.
Thread.findByIdAndUpdate(body.thread, { $push: { comments: comment.id }})
I simply find the thread by the id, then use the $push operator to push the comment id to the comments attribute where I populate later.
You can read more into the $push operator here (mongoose v3.4) https://docs.mongodb.com/manual/reference/operator/update/push/

express/mongoose update query

I having problem wrapping my head around updating multiple values in my mongoDB using mongooseJS and ExpressJS.
Let say I submit an array of 2 or more objects from my frontend to "express routing" and there I get the req.body parameters to fetch it. My req.body looks like this:
[articles:
{ article: {
_id: '564209c66c23d5d20c37bd84',
quantity: 25,
},
{ article: {
_id: '564209c66c23d5d20c37bd83',
quantity: 51,
},
}]
I then need to loop? to find the specific article in the db to update and when that article is found I want to update the "quantity" value from the frontend to the correct article in db.
var id = [];
var body = {};
for (var i = req.body.length - 1; i >= 0; i--) {
id.push(req.body[i].article._id);
body[i] = req.body[i].article.quantity;
};
Articles.update(
{ _id: {$in: id} },
{ $set: {quantity: body[0].article.quantity} },
{multi: true},
function(err, response){
if(err)
console.log(err);
console.log(response);
});
The problem with this code is that I put in the first quantity value for all articles and I want it to be the correct one from the frontend. It feels like I'm on the right path but i pretty new to mongoDB and express so if there is a better solution or even a solution let me know.
Grahlie,
If you are having issues with queries, it's sometimes useful to test queries from the mongodb shell itself to workout the logic.
If your article documents are structured as such:
{
_id: ObjectId("564209c66c23d5d20c37bd84"),
quantity: 25
}
{
_id: ObjectId("564209c66c23d5d20c37bd83"),
quantity: 51
}
If you want to update the quantity of a unique document based on it's _id then you could so with this query.
db.articles.update(
{"_id": "564209c66c23d5d20c37bd84"},
{$set : { "quantity" : 25}}
)
If you wanted to update multiple documents with the same quantity you could use $in, but that's not what you want to do. You want to loop through your req.body array and update the quantity of each article.
So your code would be as such:
var articles = req.body;
var updateArticle = function(article) {
Articles.update(
{_id:article._id},
{$set:{ quantity: article.quantity}},
function(err, article){
...
);
}
for(var i = 0, n = articles.length; i < n; i++){
updateArticle(articles.[i].article);
}

Push value to Array if key does not exist Mongoose [duplicate]

This question already has answers here:
Mongoose Unique values in nested array of objects
(2 answers)
Closed 8 years ago.
Given mongoose schema
var SomeSchema = new Schema({
// ...
members: [
{
name: String,
username: String
}
]
});
From my code I want to push object to members but only if there is no given username in array yet. How can I do it with mongoose?
You could check for the username in the condition part of the update query:
var conditions = {
_id: id,
'members.username': { $ne: 'something' }
};
var update = {
$addToSet: { members: { name: 'something', username: 'something' } }
}
SomeModel.findOneAndUpdate(conditions, update, function(err, doc) {
...
});

Updating an array item using NodeJS, MongoDB & Monk

I have a data set like this:
{
name : 'Doc Name',
photos: [
{
name: 'photo1',
url: 'http://.....'
},
{
name: 'photo2',
url: 'http://......'
}
],
etc ...
Using Monk https://github.com/LearnBoost/monk how do I update photo2? I can use an index as I am iterating over the fields at the moment.
My current attempt below gives me an error, and I can't use a variable for the JSON selector (as in the index).
collection.update({_id: data._id}, {photos[i].data: filename}, function(err, updatedata) {
});
Updating items at a position in an array can be done using the positional $ operator
collection.update(
{ _id: data.id, "photos.name": "photo2" },
{ $set: { "photos.$.data": "yourdata" } }
)
So I found a solution to my problem but there may be some better options and I will leave it unanswered. But for anyone else with the same issue this is what I did:
I extracted the MongoDB document as an object in Node.js, manipulated the document, and then replaced the entire array in a single update statement. For example here is some pseudo code:
collection.find({id: 1}, function(err, doc){
for(i=0; i< doc.array.length; i++) {
//do what you gotta do
doc.array[i].property = 'new value';
}
collection.update({id: 1}, {$set : {"doc.array": doc.array}}, function(err,doc){
console.log(err);
}
})

Resources