update an array field in the document in mongodb using nodejs - arrays

My Model:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sampleapp');
var mongoSchema = mongoose.Schema;
var Schema = mongoose.Schema;
var userprofileSchema = {
"firstname" : String,
"lastname" : String,
"gender" : String,
"username" : String,
"email" : String,
"password" : String,
"phone" : Number,
"dateofbirth": Date,
"address" : [],
"education" : [],
"workexperience" : [],
"usercertification" : [],
"skills" : [],
"sociallinks" : [],
"interest" : [],
"created_date" : {type : Date, default : Date.now},
"updated_date" : {type : Date, default : Date.now}
};
module.exports = mongoose.model('profiles',userprofileSchema);
I want to update the usercertifications array fields can any one help me over here. i have written the controller code as below using $set:
exports.updateprofile = function(req, res){
Profile.update(
{ '_id': req.body.id },
{ $set: { 'address.$.city': req.body.city }},
(err, result) => {
if (err) {
res.status(500)
.json({ error: 'Unable to update competitor.', });
} else {
res.status(200)
.json(result);
}
}
);
};

Your code need really refactoring:
// User.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userProfileSchema = new Schema({
"firstname" : String,
"lastname" : String,
"gender" : String,
"username" : String,
"email" : String,
"password" : String,
"phone" : Number,
"dateofbirth": Date,
"address" : [String], // define schema, this is my eg. - array of numbers
"education" : [{ school: String }], // define schema, this is my eg. - array of objects
"workexperience" : [], // define schema
"usercertification" : [], // define schema
"skills" : [], // define schema
"sociallinks" : [], // define schema
"interest" : [], // define schema
"created_date" : {type : Date, default : Date.now},
"updated_date" : {type : Date, default : Date.now}
});
module.exports = mongoose.model('Profile', userProfileSchema);
In main file or in routes
... some requires
const mongoose = require('mongoose');
const Profile = require('..path to User.model.js');
mongoose.connect('mongodb://localhost/sampleapp');

Related

Mongoose populate nested array with aggregate

I'm learning mongoose and I'm trying to populate everything from the account schema with the aggregate function.
I'm getting some trouble when I'm trying to populate the fields $account.sessions.trades.closes.timeframe and $account.sessions.trades.tag. The goal of the query is to get something like this
[
{ // trade 1
name : "account-name",
session : {name : "session-name"},
trade : {
symbol : {...},
open : {....},
closes : {
gain : "12",
timeframe : {time : 12, unit : "min"}
},
tags : [
{name: "tag-name-1"},
{name: "tag-name-2"}
],
}
},
{ // trade 2
...
},
{ // trade 3
...
}
]
Account
const accountSchema = new Schema({
name : { type : String, required: true},
sessions : [{
type : Schema.Types.ObjectId,
ref : "Session_Model"
}],
});
Session
const sessionSchema = new Schema({
name : {type : String},
trades : [{
type : Schema.Types.ObjectId,
ref : "Trade_Model"
}],
});
Trade
var operationSchema = new Schema({
gain : { type: Number },
timeframe : { type: Schema.Types.ObjectId, ref : "Timeframe_Model"},
});
const tradeSchema = new Schema({
symbol : { type: Schema.Types.ObjectId, ref : "Symbol_Model"},
open : operationSchema,
closes : [operationSchema],
tags : [{type: Schema.Types.ObjectId, ref : "Tag_Model"}],
});
Timeframe
const timeframeSchema = new Schema({
time : { type: Number, required: true },
unit : { type: String, required: true },
});
Aggregate query
Account_Model.aggregate(
[
{$lookup : {
from : "session_models",
localField : "sessions",
foreignField : "_id",
as : "populate_sessions"
}},
{$lookup : {
from : "trade_models",
localField : "populate_sessions.trades",
foreignField : "_id",
as : "trade"
}},
{$unwind : "$trade"},
{$sort : {"trade.open.date" : 1}},
{$skip : Number(req.params.limit) * (Number(req.params.page)-1)},
{$limit : Number(req.params.limit)},
{$lookup : {
from : "symbol_models",
localField : "trade.symbol",
foreignField : "_id",
as : "trade.symbol"
}},
{$unwind : { path : "$trade.symbol"}},
{$lookup : {
from : "timeframe_models",
localField : "trade.open.timeframe",
foreignField : "_id",
as : "trade.open.timeframe"
}},
{$unwind : { path : "$trade.open.timeframe"}},
{$lookup : {
from : "session_models",
localField : "trade.session_id",
foreignField : "_id",
as : "session"
}},
{$unwind : { path : "$session"}},
{$match : {}},
{$project : {
"name" : 1,
"trade" : 1,
"session.name" : 1,
}
}
]
).then(accounts => { ... })
Thanks for your help.

Trying to remove _id in an array. It does not seem to work

I'm trying to delete the second player in the array. but everything I try doesn't work. Any help is appreciated
Here is the stored data
{
"_id" : ObjectId("5cdd9dfe331fa63911455c4f"),
"name" : "goobers",
"venue" : ObjectId("5cdc96a4f957961fed9316dd"),
"league" : ObjectId("5cdc96b5f957961fed9316de"),
"duespaid" : 1,
"players" : [
{
"_id" : ObjectId("5cdc96c7f957961fed9316fe"),
"captain" : 1
},
{
"_id" : ObjectId("5cdc96cbf957961fed9316ff")
}
],
"__v" : 1
}
Here is what I thought would work
db.leagues.update({
_id:ObjectId("5cdd9dfe331fa63911455c4f")
}, {
$pull: {
"players": {
"_id": ObjectId("5cdc96cbf957961fed9316ff")
}
}
})
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Here is the SCHEMA
var mongoose = require("mongoose");
//Scheme setup
var teamSchema = new mongoose.Schema({
name: String,
venue: {
type: mongoose.Schema.Types.ObjectId,
ref: "Venue"
},
league: {
type: mongoose.Schema.Types.ObjectId,
ref: "League"
},
players: [{
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Player"
},
captain: Number,
name: String
}],
duespaid: Number
});
//var Campground = mongoose.model("League", leagueSchema);
module.exports = mongoose.model("Team", teamSchema);
I got this solved now... the issue was in my Schema setup.. mongoose didn't like me calling the object id. Now im able to push to the correct location and it all works.

MongoDB Get Single Object Nested in Array of Objects in Array of Objects

How do you access a single object nested in an array of objects that is nested in another array of objects, based on a few property values, something like this in pseudo code:
SELECT DAY=1 WHERE _id=5a3469f22dc3784bdd9a6190 AND MONTH=12
Mongoose model schema is listed below. As required, subdocuments are listed higher than their corresponding parents, dailySchedulesSchema being the highest:
var dailySchedulesSchema = new mongoose.Schema({
day: Number,
dayStart: Number,
firstBreakStart: Number,
firstBreakEnd: Number,
lunchStart: Number,
lunchEnd: Number,
secondBreakStart: Number,
secondBreakEnd: Number,
dayEnd: Number,
workDuration: Number
});
var monthlyScheduleSchema = new mongoose.Schema({
month: {type: Number, required: true },
dailySchedules: [dailySchedulesSchema]
});
var employeeSchema = new mongoose.Schema({
name: {type: String, required: true},
surname: {type: String, required: true},
email: {type: String, required: true},
phone: {type: String, required: true},
occupation: {type: String, required: true},
status: {type: Boolean, required: true},
monthlySchedule: [monthlyScheduleSchema]
});
This is the employee entry in the database I am trying to work on.:
"_id" : ObjectId("5a3469f22dc3784bdd9a6190"),
"name" : "Eric",
"surname" : "K. Farrell",
"email" : "EricKFarrell#dayrep.com",
"phone" : "864-506-7281",
"occupation" : "Employee",
"status" : true,
"monthlySchedule" : [
{
"month" : 12,
"dailySchedules" : [
{
"day" : 1,
"dayStart" : 480,
"firstBreakStart" : 600,
"firstBreakEnd" : 615,
"lunchStart" : 720,
"lunchEnd" : 750,
"secondBreakStart" : 870,
"secondBreakEnd" : 885,
"dayEnd" : 1020,
"workDuration" : 480
},
{
"day" : 2,
"dayStart" : 540,
"firstBreakStart" : 630,
"firstBreakEnd" : 645,
"lunchStart" : 750,
"lunchEnd" : 780,
"secondBreakStart" : 870,
"secondBreakEnd" : 885,
"dayEnd" : 1050,
"workDuration" : 480
}
]
}
]
}
The route itself for getting single day is: "/employees/:employeeid/:month/:day" .
While I managed to access the parent documents(like listing all employees), I was unable to list specific subdocument entries(like specific day schedule for that employee) - mongoose has either been returning all of the existing day schedules in the month or nothing at all:
(...)
var sendJsonResponse = function(res, status, content){
res.status(status);
res.json(content);
}
(...)
module.exports.empDayReadOne = function(req, res){
var monthParam = req.params.month;
var employeeid = req.params.employeeid;
var dayParam = req.params.day;
Emp
.aggregate([
{$match: {$and: [{'monthlySchedule': {$elemMatch: {$exists: true} } }, {_id: employeeid }] } },
{$unwind:'$monthlySchedule'},
{$unwind:'$monthlySchedule.dailySchedules'},
{$match:{ $and:[ {'monthlySchedule.dailySchedules.day': dayParam},{'monthlySchedule.month': monthParam} ] } }
])
.exec(function(err, dailySchedule){
if(dailySchedule){
sendJsonResponse(res, 200, dailySchedule);
} else if(err){
sendJsonResponse(res, 400, err);
return;
} else {
sendJsonResponse(res, 404, {"message": "This day has no schedules added."});
return;
}
});
};
You can try below aggregation query.
The below query first $filters monthlySchedule which returns the array with the matching month array element followed by second filter to retrieve the matching day element in dailySchedules array.
$arrayElemAt to convert the array with single element into a document.
db.collection_name.aggregate([
{"$match":{"_id":ObjectId("5a3469f22dc3784bdd9a6190")}},
{"$project":{
"dailyschedule":{
"$arrayElemAt":[
{"$filter":{
"input":{
"$filter":{
"input":"$monthlySchedule",
"cond":{"$eq":["$$this.month",12]}
}
},
"cond":{"$eq":["$$this.day",1]
}
}},
0]
}
}}
])
Updated Mongoose code:
Emp.aggregate([
{"$match":{"_id":mongoose.Types.ObjectId(employeeid)}},
{"$project":{
"dailyschedule":{
"$arrayElemAt":[
{"$filter":{
"input":{
"$filter":{
"input":"$monthlySchedule",
"cond":{"$eq":["$$this.month",monthParam]}
}
},
"cond":{"$eq":["$$this.day",dayParam]
}
}},
0]
}
}}
])

mongoDB - How to update/insert a field in an object which is within an array?

I have a method which inserts a new document into the collection "items".
//Example data of variables
var home = "home1";
var itemId = "123";
var username = Meteor.user().username;
//Upsert command
items.upsert({
'_id': home
}, {
$push: {
'createdItems': {itemId, username, home}
}
});
This creates a document like this:
"_id" : "home1",
"createdItems" : [
{
"itemId" : "123",
"username" : "Jon Doe",
"home" : "home1"
},
{
"itemId" : "456",
"username" : "Jon Doe2",
"home" : "home1"
},
{
"itemId" : "789",
"username" : "Jon Doe3",
"home" : "home1"
}
]
}
Now I need to be able to update the existing fields and insert new fields into these objects later. The itemId within these objects is the "reference". So I need a mongoDB function which inserts or updates fields by using the "itemId" as a query operator. Something like this:
//update a field
items.upsert({
'itemId': "123"
}, {
$set: {
'createdItems': {username: "Clark Kent"}
}
});
//insert new field
items.upsert({
'itemId': "123"
}, {
$set: {
'createdItems': {Value: 1000}
}
});
Or do I have to use $push? These commands are not delivering the results that I need. At the end the document should look like this:
"_id" : "home1",
"createdItems" : [
{
"itemId" : "123",
"username" : "Clark Kent",
"home" : "home1",
"Value" : 1000
},
{
"itemId" : "456",
"username" : "Jon Doe2",
"home" : "home1"
},
{
"itemId" : "789",
"username" : "Jon Doe3",
"home" : "home1"
}
]
}
Or do I have to use another data schema for the collection? If yes, which one can I choose when I want to have "itemId, "username" and "home" still in an array but "packed together"?
Many thanks.
If you want to update object in array query below will work fine
items.update({
'createdItems.itemId': '123'
}, {
$set: {
'createdItems.$.username': 'Clark Kent'
}
})
You can also easily add new fields to the object using the same query.
items.update({
'createdItems.itemId': '123'
}, {
$set: {
'createdItems.$.username': 'Clark Kent'
'createdItems.$.newField': 'newFieldValue'
}
})

Query on array of array object in mongodb

Following is my product collection in mongodb..
{
"_id" : ObjectId("56d42389db70393cd9f47c22"),
"sku" : "KNITCHURI-BLACK",
"options" : [
{
"sku" : "KNITCHURI-BLACK-M",
"stores" : [
{
"code" : "6",
"quantity" : 0
},
{
"code" : "10",
"quantity" : 26
}
],
"ean_code" : "2709502",
"size" : "M"
},
{
"sku" : "KNITCHURI-BLACK-S"
"stores" : [
{
"code" : "6",
"quantity" : 0
},
{
"code" : "10",
"quantity" : 30
}
],
"size" : "S"
}
]
}
want query on where { 'options.stores.code' : '6' } and { 'options.stores.quantity' : { $gt : 0 } }, How i query on this collection then i got response? Kindly help on this issue..
Here is the two approaches to get documents in Mongoose.
You can change the Mongo query if required as given in the various answers. I have just used your approach for Mongo query.
Approach 1 - Using cursor - Recommended Approach
Approach 2 - Using Query
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var Schema = mongoose.Schema, ObjectId = Schema.ObjectId;
var Store = new Schema({
code : String,
quantity : Number
});
var Option = new Schema({
sku : String,
stores : [ Store ],
ean_code : String,
size : String
});
var productSchema = new Schema({
_id : ObjectId,
sku : String,
options : [ Option ]
});
var Product = mongoose.model('product', productSchema, 'product');
console.log("Cursor Approach #1");
var cursor = Product.find({
'options.stores' : {
$elemMatch : {
code : '6',
quantity : {
$gt : 0
}
}
}
}).cursor();
console.log("Curosr Results***************************************");
cursor.on('data', function(doc) {
console.log("Getting doc using cursor ==========>" + JSON.stringify(doc));
});
cursor.on('close', function() {
console.log("close the cursor");
});
console.log("Query Approach #2");
var query = Product.find({
'options.stores' : {
$elemMatch : {
code : '6',
quantity : {
$gt : 0
}
}
}
});
console.log("Query Results***************************************");
query.exec(function(err, doc) {
if (err) {
console.log(err);
}
console.log("Getting doc using query ==========>" + JSON.stringify(doc));
});
I think you need to unwind options
db.product.aggregate( [
{ $unwind: "$options" }
{ $match: { 'options.stores.code' : '6','options.stores.quantity' : { $gt : 0 }}
] )
As far as I understand the question, you want to find a products that are in stock in stores with code 6. The following query does that:
db.collection.find({"options.stores" : {$elemMatch: {"code" : "6", "quantity" : {$gt : 0}}}});

Resources