I have a schema
var mySchema = new Schema({
array: []
});
var PSchema = mongoose.model('objects', mySchema);
I've added 1 element called 'hello' to the array property in a schema object
var newObject = new PSchema;
newObject.array.push('hello');
newObject.save(function (err) {});
I want to update the schema object to add 'hello2' to the array property if and only if hello2 doesn't already exist in the array.
Is this possible with mongoose? If so, how do i do this?
You can make use of the find() function and then perform an update.
PSchema.find({},function(err,docs){
docs.forEach(function(doc){
if(doc.array.indexOf("hello2") == -1)
{
doc.array.push("hello2");
doc.save(function (err) {
if(err) {
//error
}
});
}
})
})
Related
Lets say I got a mongodb table named "bookings", and another named "users" etc etc..
Would it be possible to call a function using a variable/parm as the table name?
Like this:
let myData = getRecord("bookings", "ABCDE")
let myData = getRecord("users", "Torben")
Here is my suggestion to the code.
var mongoose = require('mongoose');
var getRecord = (tableName, recordID) => {
return new Promise((resolve, reject) => {
tableName.findOne (
{ "_id": recordID }
,function(err, data) {
if (err) {
return reject(new Error('getRecord ERROR : ' + err));
}
if (!data) {
return reject(new Error('Record Not Found!'));
}
return resolve(data);
})
})};
let myData = getRecord("bookings", "ABCDE")
Normally you define schemas in mongoose, so you probably defined it somewhere like that:
var Bookings = mongoose.model('Bookings', bookingSchema);
Now you can just call your code with The class as parameter instead of a string:
let myData = getRecord(Bookings, "ABCDE")
And you getRecord function should work with your code.
Why is it better to use variables/classes instead of strings?
When using the variables directly your IDE will display an error if you make a mistake in the variable name, that wont happen if you just pass a string and make a typo there.
Not quite like that. But you can assign the schemas you create to properties of an object, then use the variable name to look up those properties. So for instance:
tables = {
bookings: new Schema({ ... }),
users: new Schema({ ... })
};
Then in your function, you'd just do:
tables[tableName].findOne(...)
What should I do to stop the post request from posting new object if the object already exists?
I have pasted my code and json object. I have tried next(); but it doesnt work and a duplicate object with some other id is created no matter what. I am using before beforePostTransaction function to check if the product already exists. The request contains the id and the store id of the
index.js
const Transaction = require('./transactions/TransactionModel');
const TransactionCTL = require('./transactions/TransactionController');
Transaction.before('post', TransactionCTL.beforePostTransaction);
Transaction.register(router, '/transactions');
TransactionController.js
const beforePostTransaction = (req, res, next) => {
var id = req.body.id;
Transaction.findById(
id,
(err, data)=>{
if (!data){
next();
}
else{
var store = data.store;
store = JSON.stringify(store);
store = store.replace(/\"/g, "");
if(store !== req.body.store){ //update the whole object
next();
}
else{
//do what?
}
}
});
res.sendStatus(409);
}
json object
[{
"_id": "596db06849822a13c97ba3f9",
"store": "596b088131ea400490897c50"
}]
Not sure what is your model. But if it is mongoose you can use method
.findOneAndUpdate(query,
update,
{upsert: true},
function (error, result) {
if (!error) { //if you need to do something else
}
});
Where update is your object. It will create new item if it not exist and update it if it exist.
I am trying to use mongoose addToSet to add multiple ObjectIds to a sub-doc array. I've used a similar method for adding a single subdocument, but I'm trying to figure out how to add multiple subdocuments.
Project Model
import mongoose from 'mongoose';
var Schema = mongoose.Schema;
const ProjectSchema = new Schema({
title: {
type: String
},
files: [{
type: Schema.ObjectId,
ref: 'File'
}]
});
export default mongoose.model('Project', ProjectSchema);
File Model
import mongoose from 'mongoose';
var Schema = mongoose.Schema;
const FileSchema = new Schema({
fileUrl: {
type: String
},
date: {
type: Date
}
});
export default mongoose.model('File', FileSchema);
Controller
Project.create({fileUrl: req.fileUrl}, (err, proj) => {
if (err) {
console.log(err);
return res.status(400).send(err);
} else {
File.distinct('_id', {date: {"$lt": req.date }}).exec((err, files) => {
if (err)
return (err)
var added = new File([files]) <-----THE PROBLEM
proj.files.addToSet(added)
proj.save()
return res.status(200).send('OK');
})
}
});
//Usually I would do something like this if I were adding one subdocument to an array:
(example)
var foo = new File(file)
proj.files.addToSet(foo)
proj.save()
You are very close! When you're passing the added variable, you are not sending the list of values through. You are basically sending a single object of arrays.
If you'd like to perform the addToSet function, try doing a simple iteration:
files.forEach(function(f) {
var added = new File(f)
proj.files.addToSet(added);
proj.save(function(err, saved){
if (err)
throw (err)
return;
})
});
You can find more examples of javascript iterators here:For-each over an array in JavaScript? There is an amazing and comprehensive list of options for you.
I am trying to write a nodejs script that fetches data from multiple collections in mongodb. after that the complete data has to be written into one json response.
Currently the approach i have taken is pushing the json data from each collection into an array, and then sending the array as a response. but in the client side script i am unable to read the data.
The code (Router.js) I have written to write the response is:
appTableProdSchema.js
var conn = require('mongoose');
module.exports = conn.model('AppTableProd', {
snapShotTime : String,
nfs: Array,
hive: Array,
beeline: Array,
hs2: Array,
beeswax: Array,
df: Array
});
hs2_10010Schema.js
var conn = require('mongoose');
module.exports = conn.model('hiveserver2_10010', {
snapShotTime : String,
hs2: Array
});
Router.js
var moment = require('moment'); //add moment
var records;
//mongoose schema
var appTableProdSchema = require("./appTableProdSchema.js");
var hs2 = require("./hs2_10010Schema.js");
router.get('/getHealthReport', function(req, res) {
// Return the most recent document
var fullData = [];
records = appTableProdSchema
.find()
.sort({'_id': -1})
.limit(1)
.exec(function(err, data) {
if (err) return res.sendStatus(500);
fullData.push(data);
});
records = hs2
.find()
.sort({'_id': -1})
.limit(1)
.exec(function(err, data) {
if (err) return res.sendStatus(500);
fullData.push(data);
res.json(fullData);
});
});
module.exports = router;
The data that i see in Response is:
[
[{
"_id":"56f178cf64dadf6411ccc3fa",
"snapShotTime":"2016-03-22-16:50:05",
"__v":0,
"df":["data_node_1","data_node_2","data_node_3","data_node_4","data_node_5","data_node_13","data_node_10","data_node_9","data_node_6","data_node_8","data_node_12","data_node_7","data_node_11","ebdp-ch2-d146p.sys.comcast.net","ebdp-ch2-d192p.sys.comcast.net"],
"beeswax":["data_node_10","data_node_1","data_node_11","data_node_13","data_node_4","data_node_2","data_node_3","data_node_6","data_node_12","data_node_5","data_node_7","data_node_8"],
"hs2":["data_node_7","data_node_1","data_node_10","data_node_13","data_node_4","data_node_3","data_node_2","data_node_9","data_node_11","data_node_5","data_node_8","data_node_6","data_node_12"],
"beeline":["data_node_10","data_node_1","data_node_11","data_node_13","data_node_4","data_node_2","data_node_3","data_node_6","data_node_12","data_node_5","data_node_7","data_node_8"],
"hive":["data_node_4","data_node_2","data_node_3","data_node_7","data_node_8","data_node_5","data_node_1","data_node_6","data_node_12","data_node_11","data_node_13","data_node_9","data_node_10"],
"nfs":["data_node_7","data_node_4","data_node_1","data_node_3","data_node_10","data_node_5","data_node_13","data_node_9","data_node_11","data_node_6","data_node_8","data_node_12","data_node_2"]
}],
[{
"_id":"56f178cf64dadf6411ccc3fb",
"snapShotTime":"2016-03-22 16:50:05",
"__v":0,
"hs2":["data_node_9"]
}]
]
How do i code to get the json objects from the array ?
Array in JSON objects have a function getJSONObject(int index), you can loop through all of them using for-loop:
var array;
for(int n = 0; n < array.length(); n++)
{
var object = array.getJSONObject(n);
// do some stuff....
}
My query is:
db.Room.find({}, function (err, rooms) {
if (!err) {
async.each(rooms, function (room, done) {
db.User.find({}, function (err, users) {
if (err) {
done(err)
} else {
room.users = users
room._name = room.name
done()
}
})
}, function (err) {
if (!err) {
socket.emit('read:rooms', rooms)
}
})
}
})
and schemas are:
room:
var mongoose = require('mongoose')
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var Room = new Schema({
name: String
});
module.exports = Room
user:
var mongoose = require('mongoose')
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var User = new Schema({
email: String
});
module.exports = User
but in front-end:
socket.on('read:rooms', function (rooms) {
$scope.rooms = rooms
})
but rooms has no users property, help me, please
It's because the Rooms schema doesn't have a users property.
So, there are a few ways to fix it. Since it looks like though you want the users property to be something that really isn't part of the schema, and is a client-side join rather than work that is done on the database (which is a good!), I'd suggest you convert the data to be just plain old JavaScript objects when you send it over the socket (this would have happened anyway, you're just doing it a bit earlier).
So, when the find returns, it is actually returning a fully-realized MongooseJS model object. While you can set dynamic properties on the object instance, they aren't part of the "data" of the model, so that when it is serialized later to the client, only the properties that are documented will be available.
So, here is an example of what I'd suggest:
db.Room.find({}, function (err, rooms) {
if (!err) {
var oRooms = [];
async.each(rooms, function (room, done) {
/* etc. your code */
} else {
var oRoom = room.toObject();
oRoom.users = users
oRoom._name = room.name
oRooms.push(oRoom);
done()
}
This technique would use the toObject functionality of a Model to return a JavaScript object (not a Mongoose model). That way, you can do what you'd like to the object, including adding new properties dynamically.
Later, of course, make sure you send the new array of rooms to the client:
if (!err) {
socket.emit('read:rooms', oRooms)
}