How can count the asscociation in sequelize js - node.js

When I make the following query to get the poll with option and each option have the voteCount. But it gives wring count.
router.get("/", (req, res) => {
Poll.findAll({
where: { subjectId: req.query.subjectId },
include: {
model: PollOption,
attributes: {
include: [[Sequelize.fn("COUNT", "pollVote.id"), "voteCount"]]
},
required: false,
include: {
model: PollVote,
// attributes: [],
required: false
}
},
group:['pollOptions.id']
}).then(poll => {
console.log(poll);
res.send({ poll });
});
});
I get this as the response
{
"poll": [
//Array of the poll
{
"id": 3,
"module_id": "mbbs",
"question": "Test Question Poll",
"pollOptions": [
{
"id": 1,
"pollId": 3,
"option": "Option 1",
"voteCount": 1,
"pollVotes": [
{
"id": 6,
"pollOptionId": 1,
"pollId": 3,
"userId": 3
}
]
},
{
"id": 2,
"pollId": 3,
"userId": 120,
"option": "Option 2",
"voteCount": 2,
//Vote must be 1 but return 2
"pollVotes": [
{
"id": 2,
"pollOptionId": 2,
"pollId": 3,
"userId": 1
}
]
}
]
},
{
"id": 4,
"module_id": "mbbs",
"question": "Test Question Poll 4",
"subjectId": 1,
"pollOptions": [
{
"id": 3,
"pollId": 4,
"option": "Option 1sd",
"voteCount": 1,
"pollVotes": []
}
]
}
]
}
Where voteCount is wrong.
How can I make it right.
Sql query is as follow
SELECT poll.id, poll.module_id, poll.question, poll.userId, poll.subjectId, poll.date, poll.expireDate, pollOptions.id AS pollOptions.id, pollOptions.pollId AS pollOptions.pollId, pollOptions.userId AS pollOptions.userId, pollOptions.option AS pollOptions.option, COUNT('pollVote.id') AS pollOptions.voteCount, pollOptions->pollVotes.id AS pollOptions.pollVotes.id, pollOptions->pollVotes.pollOptionId AS pollOptions.pollVotes.pollOptionId, pollOptions->pollVotes.pollId AS pollOptions.pollVotes.pollId, pollOptions->pollVotes.userId AS pollOptions.pollVotes.userId FROM poll AS poll LEFT OUTER JOIN pollOption AS pollOptions ON poll.id = pollOptions.pollId LEFT OUTER JOIN pollVote AS pollOptions->pollVotes ON pollOptions.id = pollOptions->pollVotes.pollOptionId WHERE poll.subjectId = '1' GROUP BY poll.id;

Your sequelize statement should be as follows -
router.get("/", (req, res) => {
Poll.findAll({
where: { subjectId: req.query.subjectId },
include: {
model: PollOption,
attributes: {
include: [[Sequelize.fn("COUNT", `pollOptions->pollVotes.id`), "voteCount"]]
},
required: false,
include: {
model: PollVote,
// attributes: [],
required: false
}
},
group:['pollOptions.id']
}).then(poll => {
console.log(poll);
res.send({ poll });
});
});
Hope it helps!

Related

MongoDB: Filter by element of object in a subdocument array in aggregate function

Due to some changes to the schema, I've had a to do refactoring that's broken what was a simple filter in an application, in this instance is isToRead while everything else continues to work.
The document in "Assets" that should be appearing is:
{
"_id": {
"$oid": "ID"
},
"userId": "ID",
"folderId": "ID",
"title": "Title",
"note": "<p><strong>Note.</strong></p>",
"typeOfAsset": "web",
"isFavourite": false,
"createdAt": {
"$date": {
"$numberLong": "1666702053399"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1666702117855"
}
},
"isActive": 3,
"tags": [],
"traits": [
{
"$oid": "6357dae53298948a18a17c60"
}
]
"__v": 0
}
… and the reference document in "Assets_Traits" that I'm attempting to filter against should be:
{
"_id": {
"$oid": "6357dae53298948a18a17c60"
},
"userId": "ID",
"numberOfViews": 1,
"isToRead": true,
"__v": 0
}
I'll share the entire method, which includes the various attempts that — for whatever reason — won't work.
let tags = args.tags ? args.tags.split(',') : []
let tagsToMatch = []
if (tags.length > 0) {
tags.forEach(tag => {
tagsToMatch.push(new mongoose.Types.ObjectId(tag))
})
}
let search = {
...(args.phraseToSearch.length > 0 && {
$search: {
index: 'assets',
compound: {
must: [{
phrase: {
query: args.phraseToSearch,
path: 'title',
slop: 2,
score: { boost: { value: 3 } }
}
}],
should: [{
phrase: {
query: args.phraseToSearch,
path: 'note',
slop: 2
}
}]
}
}
})
}
let project = {
$project: {
_id: 0,
id: '$_id',
userId: 1,
folderId: 1,
title: 1,
note: 1,
typeOfAsset: 1,
isFavourite: 1,
createdAt: 1,
updatedAt: 1,
isActive: 1,
attributes: 1,
preferences: 1,
// ...(args.typeOfAttribute === 'isToRead' && {
// traits: {
// $filter: {
// input: "$traits",
// cond: { $eq: [ "$$this.isToRead", true ] }
// }
// }
// }),
tags: 1,
traits: 1,
score: {
$meta: 'searchScore'
}
}
}
let match = {
$match: {
userId: args.userId,
typeOfAsset: {
$in: args.typeOfAsset === 'all' ? MixinAssets().all : [args.typeOfAsset] // [ 'file', 'folder', 'message', 'note', 'social', 'web' ]
},
...(tagsToMatch.length > 0 && {
tags: {
$in: tagsToMatch
}
}),
...(args.typeOfAttribute === 'isToRead' && {
// $expr: {
// $allElementsTrue: [{
// $map: {
// input: '$traits',
// as: 't',
// in: {
// $and: [
// { $eq: [ "$$t.userId", args.userId ] },
// { $eq: [ "$$t.isToRead", true ] }
// ]
// }
// }
// }]
// }
// $expr: {
// $filter: {
// input: "$traits",
// cond: {
// $and: [
// { $eq: [ "$$this.userId", args.userId ] },
// { $eq: [ "$$this.isToRead", true ] }
// ]
// }
// }
// }
}),
isActive: 3
}
}
let lookup = {}
switch (args.typeOfAttribute) {
case 'areFavourites':
match.$match.isFavourite = true
break
case 'isToRead':
// match.$match.traits = {
// userId: args.userId,
// isToRead: true
// }
// match.$match.traits = {
// $elemMatch: {
// userId: args.userId,
// isToRead: true
// }
// }
// lookup = {
// $lookup: {
// from: 'assets_traits',
// let: { isToRead: '$isToRead' },
// pipeline: [{
// $match: {
// $expr: {
// $eq: [ '$isToRead', true ]
// }
// },
// }],
// localField: 'userId',
// foreignField: 'userId',
// as: 'traits'
// }
// }
break
case 'inTrash':
match.$match.isActive = 2
break
}
let skip = {
$skip: args.skip
}
let limit = {
$limit: args.first
}
let group = {
$group: {
_id: null,
count: { $sum: 1 }
}
}
let sort = {
$sort: {
[args.orderBy]: args.orderDirection === 'asc' ? 1 : -1
}
}
console.info('Queries:getAllAssetsForNarrative()', match.$match)
let allAssets = await Models.Assets.schema.aggregate(
(search.hasOwnProperty('$search')) // Order of criteria is critical to the functioning of the aggregate method.
? [search, project, match, sort, skip, limit]
: [match, project, sort, skip, limit]
// : [match, project, { $unwind: '$traits' }, { $match: { traits: { $elemMatch: { isToRead: true } } } }, sort, skip, limit]
)
let [ totalNumberOfAssets ] = await Models.Assets.schema.aggregate(
(search.hasOwnProperty('$search')) // Order of criteria is critical to the functioning of the aggregate method.
? [search, project, match, group]
: [match, project, group]
// : [match, project, { $unwind: '$traits' }, { $match: { traits: { $elemMatch: { isToRead: true } } } }, group]
)
await (() => {
if (args.phraseToSearch.length > 0) {
const SearchFactory = require('../services/search/search')
const Search = SearchFactory(Models)
Search.insertRecentSearch({
userId: args.userId,
phraseToSearch: args.phraseToSearch.toLowerCase()
})
}
})()
I removed lookup in the final two arrays for the aggregate function because it was becoming too complicated for to me understand what was happening.
Weird thing is, "Tags" match and it's also a reference, while "Assets_Traits" won't return or do anything.
The values for typeOfAsset are: [ 'file', 'folder', 'message', 'note', 'social', 'web' ]
While 'All Assets' is chosen, choosing 'To Read' performs a filter against all types of Assets, and additional filtering would happen when a specific type of Asset is chosen — as explained, this worked before the changes to the schema.
Also, ignore tags because those aren't in use here.
Thoughts appreciated!
You did not provide sample of your input (args) or the constants you use (for example MixinAssets().all which i'm suspecting is problematic).
I constructed my own input for the sake of this answer:
const args = {
typeOfAsset: 'isToRead',
typeOfAttribute: "isToRead",
tagsToMatch: ["tag1", "tag2"],
skip: 0,
first: 1,
orderBy: "_id",
orderDirection: "desc"
}
This produces the following pipeline (using your code):
db.Assets.aggregate([
{
"$match": {
"userId": "123",
"typeOfAsset": {
"$in": [
"isToRead"
]
},
"tags": {
"$in": [
"tag1",
"tag2"
]
},
"isActive": 3
}
},
{
"$project": {
"_id": 0,
"id": "$_id",
"userId": 1,
"folderId": 1,
"title": 1,
"note": 1,
"typeOfAsset": 1,
"isFavourite": 1,
"createdAt": 1,
"updatedAt": 1,
"isActive": 1,
"attributes": 1,
"preferences": 1,
"tags": 1,
"traits": 1,
"score": {
"$meta": "searchScore"
}
}
},
{
"$sort": {
"_id": -1
}
},
{
"$skip": 0
},
{
"$limit": 1
}
])
Which works, as you can see in this Mongo Playground sample.
So what is your issue? As I mentioned I suspect one issue is the MixinAssets().all if args.typeOfAsset === 'all' then you use that value, now if it's an array the match condition looks like this:
typeOfAsset: {
$in: [['web', '...', '...']]
}
This won't match anything as it's an array of arrays, if it's a constant value then again it won't match as the type in the db is different.
I will give one more tip, usually when you want to build a pagination system like this and need both the results and totalResultCount it's common practice to use $facet this way you don't have to execute the pipeline twice and you can improve perfomance, like so:
db.Assets.aggregate([
{
"$match": {
"userId": "123",
"typeOfAsset": {
"$in": [
"isToRead"
]
},
"tags": {
"$in": [
"tag1",
"tag2"
]
},
"isActive": 3
}
},
{
$facet: {
totalCount: [
{
$group: {
_id: null,
count: {
$sum: 1
}
}
}
],
results: [
{
"$project": {
"_id": 0,
"id": "$_id",
"userId": 1,
"folderId": 1,
"title": 1,
"note": 1,
"typeOfAsset": 1,
"isFavourite": 1,
"createdAt": 1,
"updatedAt": 1,
"isActive": 1,
"attributes": 1,
"preferences": 1,
"tags": 1,
"traits": 1,
"score": {
"$meta": "searchScore"
}
}
},
{
"$sort": {
"_id": -1
}
},
{
"$skip": 0
},
{
"$limit": 1
}
]
}
}
])
Mongo Playground

How to filter this array of object in Node.js?

I have some data which looks like this-
[
{
"element": 1,
"id": 1
},
{
"element": 1,
"id": 2
},
{
"element": 2,
"id": 1
},
{
"element": 2,
"id": 2
},
{
"element": 3,
"id": 1
}
]
I have data as above as it is array of object and I want to filter as given below mainly in Node.js where I want to filter with element and return new array. It will be helpful if I get any solution for this.
[
{
"element": 1,
"data": [
{
"element": 1,
"id": 1
},
{
"element": 1,
"id": 2
}
]
},
{
"element": 2,
"data": [
{
"element": 2,
"id": 1
}
]
},
{
"element": 3,
"data": [
{
"element": 3,
"id": 1
}
]
}
]
Okay, so let's get some variables in:
const elementsData = [{ element: 0001, id: 1 }, { element: 0001, id: 2 }, { element: 0001, id: 3 }, { element: 0001, id: 4 }, { element: 0002, id: 1 }, { element: 0002, id: 2 }, { element: 0002, id: 3 }, { element: 0003, id: 1 } ]
First, You'll need to filter out the unique element values:
const uniqueElements = []
elementsData.forEach(datum => {
if (!uniqueElements.includes(datum.element)) {
uniqueElements.push(datum.element)
}
})
Then do groupings by uniqueElement
// loop through the unique Elements
const output = uniqueElements.map(uniqueElement => {
// this will return the object with the specified fields
return {
// element value
element: uniqueElement,
// filter through elementsData for matching elements and save then into an array.
// You can do sort() here if you want to sort them by id, but this is basically it
data: elementsData.filter(elementData => elementsData.element === uniqueElement)
}
})

Build a JSON array of objects in node JS

I would like to build a JSON structure as below
{
"employee": {
"hireDate": "01/01/2000",
"serviceDate": "01/01/2000",
"employeeDetails": [
{
"roleName": "Analyst",
"beginDate": "01/01/2000",
"endDate": "12/31/2001",
"status": "Active"
},
{
"roleName": "Developer",
"beginDate": "01/01/2002",
"endDate": "01/01/2021",
"status": "Active"
}
],
"name": [
{
"firstName": "Jason",
"lastName": "Washington"
}
]
}
}
I'm have individual objects information as seperate resultsets from DB2 SQL. I would like to form/ build a JSON structure
Here i use one common key name as employer_id in all table result so it will easy to map all result as per employer id
let employee_details =[{
"employer_id":1,
"roleName": "Analyst",
"beginDate": "01/01/2000",
"endDate": "12/31/2001",
"status": "Active"
},{
"employer_id":1,
"roleName": "Developer",
"beginDate": "01/01/2002",
"endDate": "01/01/2021",
"status": "Active"
}
]
let employee_personal_details =[{
"employer_id":1,
"firstName": "Jason",
"lastName": "Washington"
}]
let employee_work_details = [{
"employer_id":1,
"hireDate": "01/01/2000",
"serviceDate": "01/01/2000"
}]
let employee = employee_work_details.map(details=>{
return {
...details,
employeeDetails: employee_details.filter(_details => _details.employer_id == details.employer_id),
name: employee_personal_details.filter( personal_details => personal_details.employer_id == details.employer_id)
}
})
console.log({employee})
You can use map and reduce to build an array from multiple input arrays.
We match based on some shared id, in this case employeeId.
You could make this behaviour more sophisticated by specifying a join property for each array, let's say name or date of birth.
const employees = [{ id: 1, name: "Mark Ryan" }, { id: 2, name: "Joe Smith" }, { id: 3, name: "Meg Green" }];
const employeeDetails = [{ employeeId: 1, roleName: "Analyst", beginDate: "01/01/2002" }, { employeeId: 1, roleName: "Developer", beginDate: "01/01/2005" }, { employeeId: 2, roleName: "QA", beginDate: "03/05/2015" }, { employeeId: 3, roleName: "Manager",beginDate: "11/08/2010" }];
const contactDetails = [{ employeeId: 1, email: "mark.ryan#example.com" }, { employeeId: 2, phone: "555-009" }, { employeeId: 2, email: "joe.smith#example.com" }, { employeeId: 3, email: "meg.ryan#example.com" }];
const arraysToJoin = [ { employeeDetails } , { contactDetails } ];
const result = employees.map(employee => {
return arraysToJoin.reduce( (acc, obj) => {
acc[Object.keys(obj)[0]] = Object.values(obj)[0].filter(details => acc.id === details.employeeId).map(details => {
const { employeeId, ...rest } = details;
return rest;
});
return acc;
}, employee);
});
console.log("Result:",result);

Mongodb - populate with limit on items and get total count of those items

I have a query looking like this:
const articles = await Article.find(query)
.populate({
path: 'votedUsers', // array of users id
select: 'title name username',
options: {
limit: 3,
sort: { createdAt: -1 },
},
})
.exec()
Result:
[
{
title: 'Article title',
votedUsers: [,,], // array of populated users with limit of 3
totalCountVoted: 200 // need to add this field
}
]
I want to find articles and populate votedUsers property but with limit to 3 users, but at the same time
I need to know how many ids were in votedUsers property.
For example it can be 200 users that voted on that article, but I just need to know the number and populate only 3 of them.
You can try the following aggregation using the match, lookup, project stages, and slice and size operators:
(Please note that the "users" value in lookup from must be the physical collection name.)
app.get("/article", async (req, res) => {
const data = await Article.aggregate([
{
$match: {
category: "Category1"
}
},
{
$lookup: {
from: "users",
localField: "votedUsers",
foreignField: "_id",
as: "users"
}
},
{
$project: {
title: 1,
votedUsers: { $slice: ["$users", 3] },
totalCountVoted: { $size: "$users" }
}
}
]);
res.send(data);
});
This will give you a result like this:
[
{
"_id": "5dded78f8f30c402b0fac309",
"title": "Article1",
"votedUsers": [
{
"_id": "5dded60a84523642bc27f511",
"__v": 0,
"name": "User1"
},
{
"_id": "5dded61384523642bc27f512",
"__v": 0,
"name": "User2"
},
{
"_id": "5dded61b84523642bc27f513",
"__v": 0,
"name": "User3"
}
],
"totalCountVoted": 8
},
{
"_id": "5dded7c18f30c402b0fac30a",
"title": "Article2",
"votedUsers": [
{
"_id": "5dded61b84523642bc27f513",
"__v": 0,
"name": "User3"
},
{
"_id": "5dded63c84523642bc27f514",
"__v": 0,
"name": "User4"
},
{
"_id": "5dded64484523642bc27f515",
"__v": 0,
"name": "User5"
}
],
"totalCountVoted": 8
}
]
Playground

Calculate transaction items total's and transaction item with mongoose query

In mongoose, I have a collection for transactions. Each transaction has a list of Items Something like this:
var transactionItemSchema = new mongoose.Schema({
productId: String,
quantity: Number,
price: Number
});
var transactionSchema = new mongoose.Schema({
details: String,
items: [transactionItemSchema ],
}, {
timestamps: true
});
I need to calculate each item total's value by multiplying price * quantity and rounding 2 decimals, but also I need to get the transaction total by summing all item total's in a transaction. So for example if I have this transactions in mongo:
[{
details: 'First Transaction',
items: [{
price: 5.2,
quantity: 2
}, {
price: 4,
quantity: 3
}]
}, {
details: 'First Transaction',
items: [{
price: 0.333,
quantity: 3
}]
}]
return something like this when pulling transactions:
[{
total: 22.40,
details: 'First Transaction',
items: [{
price: 5.2,
quantity: 2,
total: 10.40
}, {
price: 4,
quantity: 3,
total: 12.00
}]
}, {
total: 1.00,
details: 'Second Transaction',
items: [{
price: 0.333,
quantity: 3,
total: 1.00
}]
}]
Is there a way we can achieve this with some aggregations with mongoose?
You want $map and $multiply here.
Assuming the model is calls Transaction:
Transaction.aggregate([
{ "$addFields": {
"items": {
"$map": {
"input": "$items",
"in": {
"$mergeObjects": [
"$$this",
{ "total": { "$round": [{ "$multiply": [ "$$this.price", "$$this.quantity" ] }, 2] } }
]
}
}
}
}}
])
Or without $mergeObjects:
Transaction.aggregate([
{ "$addFields": {
"total": {
"$sum": {
"$map": {
"input": "$items",
"in": {
"$round": [{ "$multiply": [ "$$this.price", "$$this.quantity" ] }, 2]
}
}
}
},
"items": {
"$map": {
"input": "$items",
"in": {
"price": "$$this.price",
"quantity": "$$this.quantity",
"total": { "$round": [{ "$multiply": [ "$$this.price", "$$this.quantity" ] }, 2] }
}
}
}
}}
])
The $map operator is essentially used for array transforms, in which you provide an array of input and an expression to apply to each array element which defines the object output for each element. Here $multiply is applied with the two arguments to "multiply" for a result.
The $mergeObjects is optionally used as a way to take the existing object properties for each element ( price and quantity ) and include them in the output object. The alternative is to manually specify the properties in the output objects for each element, just as shown.
Of course for the document total the same is essentially supplied, but just returning a single value and feeding that to the $sum operator in order to "total" the results
All of that said, there's nothing wrong with simply manipulating the result post return from the server:
let results = await Transaction.find().lean();
// Then manipulate the items arrays
results = results.map(r =>
({
...r,
total: r.items.reduce((o, i) =>
o + parseFloat((i.price * i.quantity).toFixed(2)), 0),
items: r.items.map(i =>
({ ...i, total: parseFloat((i.price * i.quantity).toFixed(2)) })
)
})
);
Simply note the use of lean() here, which returns plain JavaScript objects rather than Mongoose Documents and thus allows you to manipulate the structure of the returned results.
Here's a full listing of both approaches:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true, useUnifiedTopology: true };
mongoose.Promise = global.Promise;
mongoose.set('debug', true);
mongoose.set('useCreateIndex', true);
mongoose.set('useFindAndModify', false);
const transactionItemSchema = new Schema({
productId: String,
quantity: Number,
price: Number
});
const transactionSchema = new Schema({
details: String,
items: [transactionItemSchema]
},{
timestamps: true
});
const Transaction = mongoose.model('Transaction', transactionSchema);
const initialData = [
{
details: 'First Transaction',
items: [
{ price: 5.2, quantity: 2 },
{ price: 4, quantity: 3 }
]
},
{
details: 'Second Transaction',
items: [
{ price: 0.333, quantity: 3 }
]
}
];
const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {
try {
const conn = await mongoose.connect(uri, opts);
// Clean data
await Promise.all(
Object.values(conn.models).map(m => m.deleteMany())
);
await Transaction.insertMany(initialData);
// Aggregate example
let result1 = await Transaction.aggregate([
{ "$addFields": {
"total": {
"$sum": {
"$map": {
"input": "$items",
"in": {
"$round": [
{ "$multiply": [ "$$this.price", "$$this.quantity" ] },
2
]
}
}
}
},
"items": {
"$map": {
"input": "$items",
"in": {
"$mergeObjects": [
"$$this",
{ "total": {
"$round": [
{ "$multiply": [ "$$this.price", "$$this.quantity" ] },
2
]
}}
]
}
}
}
}}
]);
log({ result1 });
// Plain JavaScript example
let result2 = await Transaction.find().lean();
result2 = result2.map(r =>
({
...r,
total: r.items.reduce((o, i) =>
o + parseFloat((i.price * i.quantity).toFixed(2)), 0),
items: r.items.map(i =>
({ ...i, total: parseFloat((i.price * i.quantity).toFixed(2)) })
)
})
);
log({ result2 });
} catch (e) {
console.error(e);
} finally {
mongoose.disconnect();
}
})();
And the output:
Mongoose: transactions.deleteMany({}, {})
Mongoose: transactions.insertMany([ { _id: 5d8f4dfcaf9f6a2f8ec28039, details: 'First Transaction', items: [ { _id: 5d8f4dfcaf9f6a2f8ec2803b, price: 5.2, quantity: 2 }, { _id: 5d8f4dfcaf9f6a2f8ec2803a, price: 4, quantity: 3 } ], __v: 0, createdAt: 2019-09-28T12:11:40.060Z, updatedAt: 2019-09-28T12:11:40.061Z }, { _id: 5d8f4dfcaf9f6a2f8ec2803c, details: 'Second Transaction', items: [ { _id: 5d8f4dfcaf9f6a2f8ec2803d, price: 0.333, quantity: 3 } ], __v: 0, createdAt: 2019-09-28T12:11:40.062Z, updatedAt: 2019-09-28T12:11:40.062Z } ], {})
Mongoose: transactions.aggregate([ { '$addFields': { total: { '$sum': { '$map': { input: '$items', in: { '$round': [ { '$multiply': [ '$$this.price', '$$this.quantity' ] }, 2 ] } } } }, items: { '$map': { input: '$items', in: { '$mergeObjects': [ '$$this', { total: { '$round': [ { '$multiply': [Array] }, 2 ] } } ] } } } } } ], {})
{
"result1": [
{
"_id": "5d8f4dfcaf9f6a2f8ec28039",
"details": "First Transaction",
"items": [
{
"_id": "5d8f4dfcaf9f6a2f8ec2803b",
"price": 5.2,
"quantity": 2,
"total": 10.4
},
{
"_id": "5d8f4dfcaf9f6a2f8ec2803a",
"price": 4,
"quantity": 3,
"total": 12
}
],
"__v": 0,
"createdAt": "2019-09-28T12:11:40.060Z",
"updatedAt": "2019-09-28T12:11:40.061Z",
"total": 22.4
},
{
"_id": "5d8f4dfcaf9f6a2f8ec2803c",
"details": "Second Transaction",
"items": [
{
"_id": "5d8f4dfcaf9f6a2f8ec2803d",
"price": 0.333,
"quantity": 3,
"total": 1
}
],
"__v": 0,
"createdAt": "2019-09-28T12:11:40.062Z",
"updatedAt": "2019-09-28T12:11:40.062Z",
"total": 1
}
]
}
Mongoose: transactions.find({}, { projection: {} })
{
"result2": [
{
"_id": "5d8f4dfcaf9f6a2f8ec28039",
"details": "First Transaction",
"items": [
{
"_id": "5d8f4dfcaf9f6a2f8ec2803b",
"price": 5.2,
"quantity": 2,
"total": 10.4
},
{
"_id": "5d8f4dfcaf9f6a2f8ec2803a",
"price": 4,
"quantity": 3,
"total": 12
}
],
"__v": 0,
"createdAt": "2019-09-28T12:11:40.060Z",
"updatedAt": "2019-09-28T12:11:40.061Z",
"total": 22.4
},
{
"_id": "5d8f4dfcaf9f6a2f8ec2803c",
"details": "Second Transaction",
"items": [
{
"_id": "5d8f4dfcaf9f6a2f8ec2803d",
"price": 0.333,
"quantity": 3,
"total": 1
}
],
"__v": 0,
"createdAt": "2019-09-28T12:11:40.062Z",
"updatedAt": "2019-09-28T12:11:40.062Z",
"total": 1
}
]
}

Resources