Inserting elements in array mongoose creates Object in NodeJS - arrays

I'm trying to insert documents in an array using Mongoose.
Here's the Schema:
var user = new mongo.Schema({
_id : Number,
devices:[
{
device_id : String,
type : String
}
]})
The update code in NodeJS looks like:
app.put('/user/update',function(req,res){
var obj = req.body;
users.update(
{'user.username' : obj.email},
{
'user.username' : obj.email,
'user.password' : obj.password,
'user.name.first' : obj.name,
'user.department' : obj.department,
'user.year' : obj.year,
'user.college' : obj.college,
'user.contact.phone': obj.contact,
'user.last_login' : obj.last_login,
$push:{
'devices': {
device_id: 'sadasd32u4je3bdjas',
type: 'Windows'
}
}
}, function(err){
if(err)
res.json({"foo": String(err)});
else
res.json({"foo": "Successfully Signed up!"});
});
}
);
But instead it inserts something like:
"devices": [
"[object Object]",
"[object Object]",
"[object Object]",
"[object Object]",
"[object Object]"
],
Where did I go wrong? Thanks again.

Use the findOneAndUpdate() method with the 'upsert' option set to true - this creates the object if it doesn't exist (defaults to false):
var obj = req.body;
var query = {'user.username': obj.email};
var doc = {
$set: {
'user.username': obj.email,
'user.password': obj.password,
'user.name.first': obj.name,
'user.department': obj.department,
'user.year': obj.year,
'user.college': obj.college,
'user.contact.phone': obj.contact,
'user.last_login': obj.last_login
},
$push: {
'devices': {
device_id: 'sadasd32u4je3bdjas',
type: 'Windows'
}
}
};
var options = {upsert: true};
users.findOneAndUpdate(query, doc, options, function(err){
if(err)
res.json({"foo": String(err)});
else
res.json({"foo": "Successfully Signed up!"});
});

Related

MongoDB : Complex Arrary field

{
"_id" : ObjectId("58d9084841a6168234689aee"),
"ID" : "01",
"data" : {
"Type1" : {
"value" : "ABC",
"timestamp" : "2017-03-20 16:01:01"
},
"Type2" : {
"value" : "ccc",
"timestamp" : "2017-03-20 16:01:01"
}
}
}
I want to get timestamp of each TYPE from mongodb using queryobject using nodejs.
How to get it,Please help.
var queryObject = url.parse(req.url,true).query;
var mdb = db.collection("HISTORY").find({{'timestamp':{"$gte":queryObject.fromdate,"$lt" : queryObject.todate}},{"ID":1});
Here is my node service:
function getHistory(req,res){
try{
var queryObject = url.parse(req.url,true).query;
var index=0, resultset = [];
var db1 = db.collection("HISTORY").find({$and : [{'data.Type1.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type2.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type3.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type4.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type5.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}}
]},{"Ino":1,"ID":1,"data":1});
db1.count(function(err, count) {
console.log("count" , count);
db1.each(function(err, doc) {
if(doc!=null){
var valdata=doc.alarms;
var fields = [];
var queryString ="SELECT field1,NAME FROM details c inner join locdetails l on c.loc_id=l.loc_id where no='"+doc.Ino+"' limit 1;";
var dtfield1 = null;
var dtfield2 = null;
connection.query(queryString, function(err,result){
index++;
if(err){
}else{
if(result.length>0)
{
dtfield1 = result[0].field1;
dtfield2 = result[0].NAME;
if(dtfield1!=null){
for (var x in valdata) {
var dt = new Date(valdata[x].timestamp).toISOString().replace(/T/, ' ').replace(/\..+/, '');
var compareDate = new Date(dt);
if(compareDate.getTime()>=fromDate.getTime()&&compareDate.getTime()<=toDate.getTime()){
resultset.push({"Name":dtfield1,"LName":dtfield2,"Ino":doc.Ino,"ID":doc.ID,"data":x,"datav":valdata[x].value,"Timestamp":valdata[x].timestamp});
}
if(index == count){
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.write(JSON.stringify(resultset));
res.end();
}
}} }}
});
} else {
}
});
});
}
catch (err) {
console.log("Exception -- ",err);
}
}
I want data should filter based on timestamp and same can be display in UI and download the displayed data.And also filter should be in UI like current day data and based on time filter also.
If you want search base on both Type1.timestamp and Type2.timestamp, you should use $and. you can change $and with $or if one matching one of them is enough
db.collection("HISTORY").find({
$and : [{'data.Type1.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}},
{'data.Type2.timestamp':{"$gte": new Date(queryObject.fromdate),"$lt" : new Date(queryObject.todate)}}
]
},
{ID:1}, function (err, res){
});
You can use aggregation to meet your requirements.
For your initial list which will only show the latest data values of each object, you can use the following pipeline -
[
{
$project:{
_id:1,
ID:1,
data:{ $objectToArray: "$data" }
}
},
{
$unwind:"$data"
},
{
$sort:{
"data.v.timestamp":-1
}
},
{
$group:{
_id:{
_id:"$_id",
ID:"$ID"
},
data:{
$first:"$data"
}
}
},
{
$addFields:{
data:["$data"]
}
},
{
$addFields:{
data:{ $arrayToObject: "$data" }
}
}
]
The result of the aggregation should give you an array of objects like this -
{
"_id" : ObjectId("5bc469c11f8e482416d6edb3"),
"ID" : "01",
"data" : {
"Type2" : {
"value" : "ccc",
"timestamp" : ISODate("2017-03-22T16:01:01.000+06:00")
}
}
}
As for filtering the collection to get documents with data properties that have timestamp values in the given range, the above pipeline can be modified to acquire it
[
{
$project:{
_id:1,
ID:1,
data:{ $objectToArray: "$data" }
}
},
{
$unwind:"$data"
},
{
$sort:{
"data.v.timestamp":-1
}
},
{
$match:{
"data.v.timestamp":{ $gt: "start date value", $lt: "end date value"}
}
},
{
$group:{
_id:{
_id:"$_id",
ID:"$ID"
},
data:{
$addToSet:"$data"
}
}
},
{
$project:{
_id:"$_id._id",
ID:"$_id.ID",
data:{ $arrayToObject: "$data" }
}
}
]
The result of this aggregation will produce array of objects similar to the one described above. But this time each document's data object will only have properties that match the timestamp condition.
Hope this helps. A final word of advice to you would be to rethink the schema design of the history collection. Because if simplistic date based queries are getting this difficult for you. You can only imagine what the future might hold for you with this design.

How to insert record automatically in mongodb (nodejs, express, mongoose)

I am working on a team-based project. I created a new collection with some records (inserted manually). Is there any script or code to insert these records automatically from within the code, so that my when my colleague will work they do not need to insert those records again.
Code:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ServiceCategoryTypeSchema = new Schema({
_id: {type: String},
name:String
}, {
collection:'service_category_type',
timestamps:{createdAt:'created_at', updatedAt:'updated_at'}
}
);
module.exports = {
getModel: function(db){
return db.model("ServiceCategoryType", ServiceCategoryTypeSchema)
},
schema:ServiceCategoryTypeSchema
};
This is the record, I am thinking to add automatically,
{
"_id" : "Inventory",
"name" : "Inventory"
}
{
"_id" : "Non-inventory",
"name" : "Non-inventory"
}
{
"_id" : "Service",
"name" : "Service"
}
When you have your model in, say, YourModel, then you should be able to save your data that you have in, say, yourData with something like this:
new YourModel(yourData).save(function (error, data) {
// handle errors, log success etc.
});
You can do it for as many pieces of data as you want.
When you populate the database with some data it may be a good idea to first check if the database is not populated yet.
Example
Here is a working example program that saves such data - I changed the database and collection names so that you won't mess with your real database when you run it:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var P = mongoose.Promise = require('bluebird');
mongoose.connect('mongodb://localhost/poptest');
var TestModel = mongoose.model('TestModel', new Schema({
_id: String,
name: String
}, {
collection: 'testcollection',
timestamps: {createdAt: 'created_at', updatedAt: 'updated_at'}
}
));
var sampleData = [
{_id: "Inventory", name: "Inventory"},
{_id: "Non-inventory", name: "Non-inventory"},
{_id: "Service", name: "Service"}
];
P.all(sampleData.map(i => new TestModel(i).save()))
.then(() => console.log('Data saved'))
.catch((err) => console.log('Error: ' + err))
.finally(process.exit);
You need to install mongoose and bluebird for it to work:
npm i mongoose bluebird
It creates 3 documents in the poptest database on localhost. You can verify it by running:
mongo poptest
and querying the testcollection collection:
db.testcollection.find();
You should get something like:
> db.testcollection.find().pretty();
{
"_id" : "Inventory",
"updated_at" : ISODate("2016-09-14T16:13:37.374Z"),
"created_at" : ISODate("2016-09-14T16:13:37.374Z"),
"name" : "Inventory",
"__v" : 0
}
{
"_id" : "Non-inventory",
"updated_at" : ISODate("2016-09-14T16:13:37.377Z"),
"created_at" : ISODate("2016-09-14T16:13:37.377Z"),
"name" : "Non-inventory",
"__v" : 0
}
{
"_id" : "Service",
"updated_at" : ISODate("2016-09-14T16:13:37.377Z"),
"created_at" : ISODate("2016-09-14T16:13:37.377Z"),
"name" : "Service",
"__v" : 0
}
This solution worked for me: https://github.com/Automattic/mongoose/issues/6326
'use strict'
const mongoose = require('mongoose')
const uri = 'mongodb://localhost/test'
const db = mongoose.createConnection(uri)
const Schema = mongoose.Schema
const testSchema = new Schema({
name: String,
age: Number
})
const Test = db.model('test', testSchema)
const test = new Test({ name: 'Billy', age: 31 })
db.once('connected', function (err) {
if (err) { return console.error(err) }
Test.create(test, function (err, doc) {
if (err) { return console.error(err) }
console.log(doc)
return db.close()
})
})

Mongodb Save data with nodejs

I am new in mongodb. I am simply insert the data using mongodb.My document looks:
{
"_id": ObjectId("5654085bf61deb761109d157"),
"address": "dsaddsadsad",
"email": "dsaddsadsad",
"name": "sadasdasdsad",
"__v": NumberInt(0)
}
My model looks:
// grab the mongoose module
var mongoose = require('mongoose');
// define our nerd model
// module.exports allows us to pass this to other files when it is called
module.exports = mongoose.model('users', {
name : {type : String, default: ''},
email : {type : String, default: ''},
address : {type : String, default: ''},
});
Now a user Comment on this.Then the document should be:
{
"comments": [
{
"uname": "arpit",
"uemail": "arpit#gmail.com",
"comment": "How can Make we this at good",
"posted_at": ISODate("2015-11-19T11:06:03.628Z")
},
{
"uname": "sumit",
"uemail": "sumit#ggi.net",
"comment": "this is also well for me",
"posted_at": ISODate("2015-11-19T11:06:27.172Z")
}
],
"_id": ObjectId("5654085bf61deb761109d157"),
"address": "dsaddsadsad",
"email": "dsaddsadsad",
"name": "sadasdasdsad",
"__v": NumberInt(0)
}
How can I make this document.My code is:
var Users = require("../app/models/users");
app.post('/comments/:id', function(req, res) {
var id = req.params.id; //coment id
var input = JSON.parse(JSON.stringify(req.body)); //comment data
//code should be here
});
Please help
/**users model*/
var mongoose = require('mongoose');
module.exports = mongoose.model('users', {
name : {type : String, default: ''},
email : {type : String, default: ''},
address : {type : String, default: ''},
comments: []
});
var Users = require("../app/models/users");
app.post('/comments/:id', function(req, res) {
var id = req.params.id; //coment id
var object = {}
for(var key in req.body){
object[key] = req.body[key];
}
Users
.findByIdAndUpdate(req.params.id, {$push: {"comments": object}})
.exec(function(error, result){
if(error){
console.log(error);
}
else{
console.log(result);
}
})
Test this:
Users.findByIdAndUpdate(id, {$push: {"comments":{
uname: req.body.the_uname,
uemail : req.body.the_uemail,
comment: req.body.the_comment,
posted_at: Date.now()
}
}
}).exec(function(error, res){});

Mongoose - How to add an object in a sub sub document array?

I can add an item into a sub document array but I can't add an item into a sub sub document array..
Here is my Mongoose schema :
var botSchema = {
"name" : String,
"type" : String,
"keyword" : String,
"active" : Boolean,
"cron" : String
};
var apiSchema = {
"name" : String,
"key" : String,
"secret" : String,
bots:[botSchema]
};
var userSchema = {
"email" : String,
"password" : String,
apis : [apiSchema]
};
module.exports.User = mongoose.model('user',userSchema);
How can I add a bot item to an existing API item ?
I have no problem when adding an API to the User. I do this :
User.findByIdAndUpdate(
userId, {
$push: {
apis: api
}
}, {
safe: true,
upsert: true
},
function(err, model) {
console.log(err);
console.log(model);
}
);
But i 'm trying everything to add the bot to an existing API. I tried this one :
User.findOneAndUpdate({
"_id": userId,
"apis._id": apiId
}, {
$push: {
"apis.$.bots": bot
}
},
function(err, doc) {
console.error("Error:", err);
console.log("Doc:", doc);
}
);
But i got this error shown :
CastError: Cast to undefined failed for value "[object Object]"

Properties with default values in Mongoose schema are not persisting

I have the following schema I've written using Mongoose:
var querySchema = mongoose.Schema({
quoteId: { type: String, default: '' },
zipcode: { type: String, default: '' },
email: { type: String, default: '' },
type: {type: String, default: ''},
isEmailChecked: { type: Boolean, default: true },
});
I provide values for only 3 properties in the querySchema assuming that the result of the fields will take default values when a new instance of query object is persisted:
var query = {};
query.quoteId = "1414775421426";
query.email = "myself#somewhere.com";
query.type = "Foo";
But following document is what I see as the result in the collection:
{
"_id" : ObjectId("5453c27d0e4c3f2837071856"),
"email" : "myself#somewhere.com",
"type" : "Foo",
"quoteId" : "1414775421426",
"__v" : 0
}
Should isEmailChecked and zipcode not be assigned their default values when a new instance of query object is persisted to the MongoDB database?
Following is how I am persisting an instance of the query object using ExpressJS/NodeJS:
app.post('/api/queries', function (req, res) {
QuoteQuery.create({
quoteId: req.body.query.quoteId,
type: req.body.query.type,
zipcode: req.body.query.zipcode,
email: req.body.query.email,
isEmailChecked: req.body.query.isEmailChecked,
}, function (err, query) {
if (err) {
res.send(err);
}
res.json(query);
});
});
Could somebody help me understand that why I got the isEmailChecked and zipcode properties in the resulting document in the MongoDB database?
I am using NodeJS, AngularJS and ExpressJS in my application along with MongoDB.
When you set mongoose model field it not use default value.
As workaround you can use underscore to extend mongoose model object with keys which exists in your query object like this:
_.extend(dbQueryObject, query);
Here is complete example:
var mongoose = require('mongoose');
var querySchema = mongoose.Schema({
quoteId: { type: String, default: '' },
zipcode: { type: String, default: '' },
email: { type: String, default: '' },
type: {type: String, default: ''},
isEmailChecked: { type: Boolean, default: true }
});
var db = mongoose.createConnection('mongodb://localhost:27017/stackoverflow',
{ server: { auto_reconnect: true } },
function(err) {
var QuerySchema = db.model('test', querySchema);
var query = {};
query.quoteId = "1414775421426";
query.email = "myself#somewhere.com";
query.type = "Foo";
QuerySchema.create({
quoteId: query.quoteId,
type: query.type,
zipcode: query.zipcode,
email: query.email,
isEmailChecked: query.isEmailChecked
}, function (err, query) {
process.exit(0);
});
});
Here is what in db:
{
"_id" : ObjectId("5453ce3c9f7e0d13c52abf61"),
"type" : "Foo",
"email" : "myself#somewhere.com",
"quoteId" : "1414775421426",
"__v" : 0
}

Resources