Mongoose populate nested array with aggregate - database

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.

Related

Update created a conflict on multiple arrayFilters

I'm trying to increment two different arrays in a similar fashion. Without incrementing elementC, everything works fine. If I add the elementC and use the arrayFilter on it, I get the error: update created a conflict at tasks.priority. I think this has something to do with iterating over the same object, but why and how would I solve this? My code:
const project = await Project.updateOne(
{_id: req.params.project_id},
{
$set: {'tasks.$[elementA].priority': req.body.new_state.priority, 'tasks.$[elementA].state': req.body.new_state.state},
$inc: {'tasks.$[elementB].priority': 1, 'tasks.$[elementC].priority': 2},
},
{
arrayFilters: [
{'elementA._id': req.params.task_id},
{'elementB.state': req.body.old_state.state, 'elementB.priority': {$gt: req.body.old_state.priority}},
{'elementC.state': req.body.new_state.state, 'elementC.priority': {$gt: req.body.new_state.priority}}
]
}
);
res.json(project);
schema:
const task_schema = new mongoose.Schema({
description: {
type: String
},
state: {
type: String
},
priority: {
type: Number
}
const project_schema = new mongoose.Schema({
name: {
type: String
},
description: {
type: String
},
non_public: {
type: Boolean
},
tasks: [task_schema]
Example:
{ "_id" : ObjectId("5ec274b50877c671ccf9b6c7"),
"name" : "first project",
"description" : "lorem ipsum",
"non_public" : true,
"tasks" : [ { "_id" : ObjectId("5ec27674e0db347307902ba9"),
"description" : "Lorem",
"state" : "TODO",
"priority" : 0 },
{ "_id" : ObjectId("5ec27686e0db347307902baa"),
"description" : "Ipsum",
"state" : "TODO",
"priority" : 1 },
{ "_id" : ObjectId("5ec27686e0db347307902baa"),
"description" : "Dolor",
"state" : "TODO",
"priority" : 2 },
{ "_id" : ObjectId("5ec293db751ae07a8520a703"),
"description" : "Sit",
"state" : "DOING",
"priority" : 0 },
{ "_id" : ObjectId("5ec29591ad84927c7788116d"),
"description" : "Amet",
"state" : "DONE",
"priority" : 0 },
]}
This is happening because you are trying to apply two different filters on the same array field and to update it. So, the Mongo engine is getting confused on which filter to apply.
Hint: Your arayFilters have to be mutually exclusive.

How do I search and return the field and data in a multi-level array of object?

I have a data set returned by find command in MongoDB. How do I search for the value and field of DeviceJson[] in the given data
{ location: [],
_id: 5d42d171e7ceef2a90245470,
farmName: 'Xilo',
description: 'This is test from Postman Api Request',
farmAddDate: 2019-08-01T11:48:01.883Z,
device:
[
{ _id: 5d441878f1877637cc712d07,
deviceName: 'Xki',
deviceType: 'Muc',
description:
'This is test for updation of specific data in a specfic farm .Test Pass',
deviceLocation: [Array],
Parameter: 'Hello Happy',
Topic: 'v1/Xki/11,180/Hello Happy' },
{ _id: 5d4418953968370e64c32e1f,
deviceName: 'Xki',
deviceType: 'Muc',
description:
'This is test for updation of specific data in a specfic farm .Test Pass',
deviceLocation: [Array],
Parameter: 'Hello Happy',
Topic: 'v1/Xki/11,180/Hello Happy' },
{ _id: 5d4425548b3cf92af46e2c9a,
deviceName: 'Xki',
deviceType: 'Muc',
description:
'This is test for updation of specific data in a specfic farm .Test Pass',
deviceLocation: [Array],
Parameter: 'Hello Happy 1',
Topic: 'sagita/5d42d171e7ceef2a90245470/Xki/11,180/Hello Happy 1' },
{ _id: 5d44256d8b3cf92af46e2c9b,
deviceName: ' DeviceX01',
deviceType: ' Test',
description: ' This is a test',
deviceLocation: '11.22,33.12',
Parameter: ' set',
Topic:
'sagita/5d42d171e7ceef2a90245470/ DeviceX01/11.22,33.12/ set',
DeviceJson: [Array] }
]
}
The data Set I have saved in an array called usdData=[] and was looping through its index and this is resultant and I want to search even Interior and the value of DeviceJson in the schema. How can I do so?
var usdData=[];
collection.findOne({"email":Username},function (err,doc) {
if (err) throw err;
usdData=doc.farm;
for (let index = 0; index < usdData.length; index++) {
if (usdData[index].farmName === gotfarmName) {
return usdData[index];
}
const element = usdData[index];
// const dElement = JSON.stringify(element);
// console.log("Array started here \n"+dElement);
// const ddElement= JSON.parse(dElement) ;
console.log(usdData[1]);
}
return console.log();
});
If you known the 'DeviceJson' structure you can do something like this:
01) Example of Document:
{
"_id" : "5d42d171e7ceef2a90245470",
"location" : [],
"farmName" : "Xilo",
"description" : "This is test from Postman Api Request",
"farmAddDate" : "2019-08-01T11:48:01.883Z",
"device" : [
{
"_id" : "5d441878f1877637cc712d07",
"deviceName" : "Xki",
"deviceType" : "Muc",
"description" : "This is test for updation of specific data in a specfic farm .Test Pass",
"deviceLocation" : [],
"Parameter" : "Hello Happy",
"Topic" : "v1/Xki/11,180/Hello Happy"
},
{
"_id" : "5d4418953968370e64c32e1f",
"deviceName" : "Xki",
"deviceType" : "Muc",
"description" : "This is test for updation of specific data in a specfic farm .Test Pass",
"deviceLocation" : [],
"Parameter" : "Hello Happy",
"Topic" : "v1/Xki/11,180/Hello Happy"
},
{
"_id" : "5d4425548b3cf92af46e2c9a",
"deviceName" : "Xki",
"deviceType" : "Muc",
"description" : "This is test for updation of specific data in a specfic farm .Test Pass",
"deviceLocation" : [],
"Parameter" : "Hello Happy 1",
"Topic" : "sagita/5d42d171e7ceef2a90245470/Xki/11,180/Hello Happy 1"
},
{
"_id" : "5d44256d8b3cf92af46e2c9b",
"deviceName" : "DeviceX01",
"deviceType" : " Test",
"description" : " This is a test",
"deviceLocation" : "11.22,33.12",
"Parameter" : " set",
"Topic" : "sagita/5d42d171e7ceef2a90245470/ DeviceX01/11.22,33.12/ set",
"DeviceJson" : [
{
"_id" : "5db85e439a17899b8ba631cd",
"name" : "deviceJsonOne",
"complexObject" : {
"_id" : "5db85e439a17899b8ba631ce"
},
"someArray" : [
{
"someThing" : 1
},
{
"someThing" : 2
}
]
},
{
"_id" : "5dae22702486f7d89ba7633c",
"name" : "deviceJsonTwo",
"complexObject" : {
"_id" : "5db85e439a17899b8ba631cf"
},
"someArray" : [
{
"someThing" : 3
},
{
"someThing" : 2
}
]
}
]
}
]
}
02) Query:
db.Collection.aggregate([
// INITIAL FILTER... HERE YOU CAN FILTER FOR ANY FILTERS...
{
$match: { "device._id" : "5d44256d8b3cf92af46e2c9b"}
},
// TRANSFORMING EVERY ELEMENT OF THE ARRAY 'device' AS A SINGLE ROW/DOCUMENT...
// EXAMPLE:
// {id: 123, "someArray":["A","B","C"]}
// --> unwind : 'someArray'
// --> [{"id": 123, "someArray": "A"},{"id": 123, "someArray": "B"},{"id": 123, "someArray": "C"}]
{
$unwind: '$device'
},
// FILTERING THE DEVICES THAT HAVE THE 'DeviceJson' PROPOERTY...
{
$match: { "device.DeviceJson" : {$exists: true}}
},
// TRANSFORMING EVERY ELEMENT OF THE ARRAY 'DeviceJson' AS A SINGLE ROW/DOCUMENT...
{
$unwind: '$device.DeviceJson'
},
// FILTERING THE ELEMENTS IN "DeviceJson"...
{
$match: { "device.DeviceJson.complexObject._id" : "5db85e439a17899b8ba631cf"}
},
// CREATING A FIELD TO STORE THE RESULT...
{
$addFields: {"DeviceJson" : "$device.DeviceJson" }
},
// SHOWING ONLY THE FIELD 'DeviceJson' IN THE RESULT...
{
$project: {"DeviceJson" : 1}
}
]);
03) Response:
{
"_id" : "5d42d171e7ceef2a90245470",
"DeviceJson" : {
"_id" : "5dae22702486f7d89ba7633c",
"name" : "deviceJsonTwo",
"complexObject" : {
"_id" : "5db85e439a17899b8ba631cf"
},
"someArray" : [
{
"someThing" : 3
},
{
"someThing" : 2
}
]
}
}

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.

update an array field in the document in mongodb using nodejs

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');

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