how to populate nested objects - reactjs

I am using MERN stack.
I have to populate the objects that was in pair of object the following is my schema.
var schema = new mongoose.Schema({
rounds:{
t_tag:{
type:String,
},
schedule:[
{
teamone:{
type:ObjectId,
ref:"Team"
},
teamtwo:{
type:ObjectId,
ref:"Team"
},
}
}
]
i have to populate teamone and teamtwo. I have tried the following code.
.populate({
path:'rounds',
populate:{
path:'schedule',
model:"Team",
},

You need to call populate and pass the ref as the argument, this should populate all objects from the same collection:
.populate("Team")
In your example:
.populate({path:"Team"})
For multiple paths you can simply chain the populate method:
.populate({path:"Team"}).populate({path:"Some other ref"})

Related

Push/Pull values on nested array mongoose

Im trying to update a value in a nested Array in a mongoose schema using express. I have the code required in place what i figuered i needed to update it, but the array doesn't get updated.
So the idea is to be able to have an array of data base schema objects with two fields, schemaName and schemaFields. I want to be able to update (add/remove)the values from schemaFields field of a specific schema object as needed.
I've already tried a bunch of stuff on here and elsewhere on the internet but nothing appears to work. I tried using findOneAndUpdate, findByIdAndUpdate etc.
My mongoose schema is as follows,
let databaseSchema = new Schema({
schemaName: { type: String },
schemaFields: [String]
});
let databaseSchemas = new Schema(
{
dbSchemas: [databaseSchema]
},
{
collection: 'databaseSchemas'
}
);
my update function is as follows,
schemasModel.mongo
.update(
{
_id: req.body.documentId,
'dbSchemas._id': req.body.schemaId
},
console.log('preparin to push the field \n'),
{
$push: {
'dbSchemas.$.schemaFields': req.body.newField
}
}
)
.then(() => {
res.send('new field added successfully');
});
So I solved it by removing the console.log() as a second argument to the model.update() function. Apparently this has to be the object with the operation.
The working code for the Model.update function is as follows,
schemasModel.mongo
.update(
{
_id: req.body.documentId,
'dbSchemas.schemaName': req.body.schemaToSearch
},
{
$push: {
'dbSchemas.$.schemaFields': req.body.newField
}
}
)
.then(() => {
res.send('new field added successfully');
});

Pushing onto Mongo SubDoc of SubDoc array

I'm going around in circles with this one so hoping someone can help. I'm building a nodejs application that receives sensor values from nodes. There can be multiple sensors on a node.
Using NodeJS, Mongod DB and Mongoose, all running on a raspberry pi, 3 I've built the following Schemas & Model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var valueSchema = new Schema ({
timestamp: {type: Date},
value: {}
});
var sensorSchema = new Schema ({
id: {type: Number},
type: {type: String},
description: {type: String},
ack: {type: Boolean},
values: [valueSchema]
});
var SensorNode = mongoose.model('SensorNode', {
id: {type: Number, required: true},
protocol: {},
sensors: [sensorSchema]
});
I can add in the node, and push sensors onto the sensors array, but I seem unable to push values onto the values array.
I've looked over a few other examples and questions on similar issues, and looked at using populate, but cant seem to get them to work.
Here is my code:
function saveValue(rsender, rsensor, payload) {
var value = {
values: {
timestamp: new Date().getTime(),
value: payload
}
}
SensorNode.findOneAndUpdate({
"id": rsender,
"sensors.id": rsensor
}, {
"$push": {
"sensors.$": value
}
}, function(err, result) {
if (err) {
console.log(err);
}
console.log(result);
});
}
This is returning undefined for the result and this error:
MongoError: exception: Cannot apply $push/$pushAll modifier to non-array
Values is definitely an array in the sensor schema.
I'm using readable ids rather than the auto assigned Mongo DB IDs for the sake of the UI, but I could use the MongoDB _id if that makes any difference, I don't see why it would?
Where am I going wrong ?
You're using positional operator $ so let's check the docs
The positional $ operator identifies an element in an array to update without explicitly specifying the position of the element in the array. To project, or return, an array element from a read operation, see the $ projection operator.
So sensors.$ will return one particular document from your sensors array. That's why you're getting an error. On this level of your document you can only replace this item by using $set. I bet you wanted to do something like this:
SensorNode.findOneAndUpdate({
"id": rsender,
"sensors.id": rsensor
}, {
"$push": {
"sensors.$.values": payload
}
});
This operation will just append payload to values array in one particular sensor with id equal to rsensor.

Is there any way to .populate() a mongoDB document with mongoose and save the populated object back into the model? [duplicate]

This question already has answers here:
Mongoose populate vs object nesting
(1 answer)
MongoDB relationships: embed or reference?
(10 answers)
Closed 5 years ago.
I have a question, wondering if there is any way to persist the returned document when using the Mongoose .populate() function by saving it back to the model. Also some questions on how to structure things. Here are my schemas:
var clientSchema = new Schema({
phone: String,
email: String
},
);
var menuSchema = new Schema({
itemName: String,
itemPrice: Number,
});
var transactionSchema = new Schema ({
createdBy: { type: Schema.ObjectId, ref: 'Client'},
items: [{ type: Schema.ObjectId, ref: 'Menu' }],
});
var Menu = mongoose.model('Menu', menuSchema);
var Client = mongoose.model('Client', clientSchema);
var Transaction = mongoose.model('Transaction', transactionSchema);
When I create a new Transaction with a POST request, I populate it and return the populated Transaction as a response:
{
"_id": "5a0bde94f4434c0a604341d2",
"createdBy": {
"_id": "5a0a8a3f9c348f0998ba8c2c",
"phone": "1234567890",
"email": "some#thing.com"
},
"__v": 0,
"items": [{ Many Menu objects }]
}
However, when I query the DB again with GET, I get this:
{
"_id": "5a0bde94f4434c0a604341d2",
"createdBy": "5a0a8a3f9c348f0998ba8c2c",
"__v": 0,
"items": [Array of ObjectIds]
}
I can't use .save() because the original schema only accepts ObjectId, not an entire Object.
I noticed that when I made my schema include SubDocuments, I did not really need to use the .populate() function. I simply pushed an object into the array, and it would be there when queried.
var transactionSchema = new Schema ({
createdBy: { type: Schema.ObjectId, ref: 'Client'},
items: [menuSchema], // Sub Doc
});
MongoDB Docs say creating large mutable arrays is a bad design. I could see some transactions having 50 or 100 objects. I can see this being more of a problem if I use subDocuments because file size , but I could also imagine that doing a .populate() on an array of 100 object IDs may be expensive.
I need to update the items array in the transaction schema every time the client registers an onclick function. I need to re-render that to the client, which involves a single PUT request per click. But I have to parse that array with each click, one by one. If I'm doing a .populate() on every single item in the array...that's not great. But using subDocuments would increase the filesize of the database.
I previously had a simpler schema, but thought that passing by reference would increase the integrity of the prices being rendered. Is it better to just have an array of Objects and push into that?
var transactionSchema = new Schema ({
createdBy: { type: Schema.ObjectId, ref: 'Client'},
items: [{
name: {type: String},
price: {type: Number}
}]
});

mongoose db - array insertion using create and save

How to insert array and normal variable data to mongoose database..
var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }], class: 10 })
parent.save(callback);
This is the method i know currently.
I need it to be done from the req.body. So how can I done after creating the parent object. ie
var parent = new Parent();
///code for inserting the array data and other normal datatypes
parent.save(callback);
Use the document instance like any other javascript object.
parent.children = [{ name: 'Matt' }, { name: 'Sarah' }];
parent.class = 10;
parent.save();
Just don't change it entirely (like doing parent = {...}), otherwise you'd have de-referenced the actual mongoose document instance. Only make changes on its properties like shown above.

Unique array values in Mongoose

Currently trailing out Mongoose and MongoDB for a project of mine but come across a segment where the API is not clear.
I have a Model which contains several keys and documents, and one of those keys os called watchList. This is an array of ID's that the user is watching, But I need to be sure that these values stay unique.
Here is some sample code:
var MyObject = new Mongoose.Schema({
//....
watching : {type: Array, required: false},
//....
});
So my question is how can I make sure that the values pushed into the array only ever store one, so making the values unique, can i just use unique: true ?
Thanks
To my knowledge, the only way to do this in mongoose is to call the underlying Mongo operator (mentioned by danmactough). In mongoose, that'd look like:
var idToUpdate, theIdToAdd; /* set elsewhere */
Model.update({ _id: idToUpdate },
{ $addToSet: { theModelsArray: theIdToAdd } },
function(err) { /*...*/ }
);
Note: this functionality requires mongoose version >= 2.2.2
Take a look at the Mongo documentation on the $addToSet operator.
Mongoose is an object model for mongodb, so one option is to treat the document as a normal javascript object.
MyModel.exec(function (err, model) {
if(model.watching.indexOf(watchId) !== -1) model.watching.push(watchId);
model.save(...callback);
});
Although, I do agree that mongoose should have some support for this built in the form of a validator for the collection document reference feature-- especially because most of the time you want to add only unique references.
That's how you can do it using Mongoose,
IF your upcoming value is an Array
Model
.findOneAndUpdate({ _id: yourID },
{ $addToSet: { watching: { $each: yourWatchingArr } } },
function(err) { /*...*/ }
);
IF your upcoming value is a string
Model
.findOneAndUpdate({ _id: yourID },
{ $addToSet: { watching: yourStringValue } },
function(err) { /*...*/ }
);

Resources