Related
I am having code like this
const aggregate = [];
const lookup = {
$lookup: {
from: "balances",
localField: "accountNumber",
foreignField: "account_id",
as: "bankbalance",
},
};
const unwind = {
$unwind: "$bankbalance",
};
const match = {
$match: {
"bankbalance.date": {
$gte: startDate,
$lte: endDate,
},
userId: mongoose.Types.ObjectId(userId),
isActive: 1,
type: "accountType"
},
};
const group = {
$group: {
_id: '$_id',
accountNumber:{"$first":"$accountNumber"},
balances: {
$addToSet: { date: "$$ROOT.date", amount: "$$ROOT.amount" },
},
},
};
aggregate.push(lookup);
aggregate.push(unwind);
aggregate.push(group);
aggregate.push(match);
let data = await BankAccounts.aggregate(aggregate);
this code is giving me empty [] data, if I do not use $group then its giving data like this
{
_id: 611bc2c4f9649b2c6fe4007f,
bankId: 'string',
mask: '0000',
name: 'Plaid Checking',
userId: 611bc2794d9f391bf2cd7877,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
bankTokenId: xxxxxxxxxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-17T14:08:04.058Z,
isConnected: true,
subtype: 'checking',
type: 'depository',
updatedAt: 2021-08-25T11:36:37.824Z,
isActive: 1,
bankbalance: {
_id: 61262b9bf9649b2c6fe7d67c,
ISODate: '2021-05-19T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1047.62,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-19',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
}
},
{
_id: 611bc2c4f9649b2c6fe4007f,
bankId: 'string',
mask: '0000',
name: 'Plaid Checking',
userId: 611bc2794d9f391bf2cd7877,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
bankTokenId: xxxxxxxxxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-17T14:08:04.058Z,
isConnected: true,
subtype: 'checking',
type: 'depository',
updatedAt: 2021-08-25T11:36:37.824Z,
isActive: 1,
bankbalance: {
_id: 61262b99f9649b2c6fe7d671,
ISODate: '2021-05-24T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1137.02,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-24',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
}
}
this is giving all data record again and again, here reference between 2 collection is accountNumber and account_id. I want to group all records in 1 like
{
_id: 611bc2c4f9649b2c6fe4007f,
bankId: 'string',
mask: '0000',
name: 'Plaid Checking',
userId: 611bc2794d9f391bf2cd7877,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
bankTokenId: xxxxxxxxxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-17T14:08:04.058Z,
isConnected: true,
subtype: 'checking',
type: 'depository',
updatedAt: 2021-08-25T11:36:37.824Z,
isActive: 1,
bankbalance: [{
_id: 61262b99f9649b2c6fe7d671,
ISODate: '2021-05-24T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1137.02,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-24',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
},
{
_id: 61262b9bf9649b2c6fe7d67c,
ISODate: '2021-05-19T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1047.62,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-19',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
}
]
}
also sort bankbalance by date. Any help! Thanks in advance!!
The stages are in the order
aggregate.push(lookup);
aggregate.push(unwind);
aggregate.push(group);
aggregate.push(match);
When the group stage executes, each document will have only the fields noted in that stage. i.e.
{
_id: 611bc2c4f9649b2c6fe4007f,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
balances: [ {date: ......, amount: .....} ]
}
When the match stage executes, the fields "bankbalance.date", userId, isActive, and type don't exist, so no documents satisfy the match.
I'm trying to select especific fields from this document
{
_id: 60d9295db34f1c0144c9b8d4,
title: 'Este es el titulo',
slug: 'este-es-el-titulo',
date: '2021-06-27',
category: {
_id: 60d92921b34f1c0144c9b8d2,
title: 'Categoria 1',
slug: 'categoria-1',
id: '60d92921b34f1c0144c9b8d2'
},
cover: {
_id: 60d72c815e57e6015e38a4c7,
name: 'project4.png',
alternativeText: '',
caption: '',
hash: 'project4_3e8c906bdf',
ext: '.png',
mime: 'image/png',
size: 540.02,
width: 1895,
height: 883,
url: '/uploads/project4_3e8c906bdf.png',
formats: [Object],
provider: 'local',
related: [Array],
createdAt: 2021-06-26T13:32:49.389Z,
updatedAt: 2021-06-28T01:43:57.469Z,
__v: 0,
created_by: '60d69246c6f06d00f64312b0',
updated_by: '60d69246c6f06d00f64312b0',
id: '60d72c815e57e6015e38a4c7'
},
id: '60d9295db34f1c0144c9b8d4'
}
and I want get something like this:
{
_id: 60d9295db34f1c0144c9b8d4,
title: 'Este es el titulo',
slug: 'este-es-el-titulo',
date: '2021-06-27',
category: {
_id: 60d92921b34f1c0144c9b8d2,
title: 'Categoria 1',
slug: 'categoria-1',
id: '60d92921b34f1c0144c9b8d2'
},
cover: { url: '/uploads/project4_3e8c906bdf.png'}
id: '60d9295db34f1c0144c9b8d4'
}
I'm using Strapi with Mongodb and y was trying with the following code:
const requiredData = {
title: 1,
slug: 1,
date: 1,
category: 1,
cover: { url: 1 }
}
const populateData = [
{
path: 'category',
select: ['title', 'slug']
}
]
let editorsPick = await strapi.query('posts')
.model.find({ editorsPick: true}, requiredData)
.limit(3)
.populate(populateData)
But I only have this:
{
_id: 60d9295db34f1c0144c9b8d4,
title: 'Este es el titulo',
slug: 'este-es-el-titulo',
date: '2021-06-27',
category: {
_id: 60d92921b34f1c0144c9b8d2,
title: 'Categoria 1',
slug: 'categoria-1',
id: '60d92921b34f1c0144c9b8d2'
},
id: '60d9295db34f1c0144c9b8d4'
}
(Without cover image), and then try with:
let editorsPick = await strapi.query('posts')
.model.aggregate([
{"$match": { editorsPick: true}},
{"$project": requiredData}
])
But I got an empty array []
Please I need a little help, and sorry for my english
I am building a simple messaging system and I have a messageSchema which is setup as below:
const messageSchema = new mongoose.Schema({
replyTo: {
type: mongoose.Schema.ObjectId,
ref: 'Message',
default: null,
},
name: {
type: Object,
required: [true, 'Message has a name'],
},
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
},
email: {
type: Object,
required: [true, 'Message has a email'],
},
subject: {
type: String,
required: [true, 'Message has a subject'],
},
content: {
type: String,
required: [true, 'Message has content'],
},
createdAt: {
type: Date,
default: Date.now(),
},
status: {
type: String,
default: 'unread',
required: [true, 'Message has a status'],
},});
Sample data below:
[
{
_id: ObjectId('53ed7efca75ca1a5248a281a'),
name: 'Person 1',
createdAt: ISODate('2021-01-01T01:00:00.000Z'),
subject: 'M1',
content: 'M1 content',
replyTo: null,
},
{
_id: ObjectId('53ed80bba75ca1a5248a281b'),
name: 'Person 2',
subject: 'M2 - Reply 1 to M1',
content: 'M2 content',
createdAt: ISODate('2021-01-01T02:00:00.000Z'),
replyTo: ObjectId('53ed7efca75ca1a5248a281a'),
},
{
_id: ObjectId('53ed80bba75ca1a5248a281c'),
name: 'Person 3',
subject: 'M3 - Reply 2 to M1',
content: 'M3 content',
createdAt: ISODate('2021-01-01T03:00:00.000Z'),
replyTo: ObjectId('53ed7efca75ca1a5248a281a'),
},
{
_id: ObjectId('53ed80bba75ca1a5248a281d'),
name: 'Person 4',
subject: 'M4',
content: 'M4 content',
createdAt: ISODate('2021-01-01T02:30:00.000Z'),
replyTo: null,
},
];
I am now trying to query the sample above to produce an inbox style response, so that the root message (no replyTo) is the top-level message, has a latest node with latest message info, and has children(if any) in a children node. See below for desired output.
[
{
_id: ObjectId('53ed7efca75ca1a5248a281a'),
name: 'Person 1',
createdAt: ISODate('2021-01-01T01:00:00.000Z'),
subject: 'M1',
content: 'M1 content',
replyTo: null,
latest: {
_id: ObjectId('53ed80bba75ca1a5248a281c'),
name: 'Person 3',
subject: 'M3 - Reply 2 to M1',
content: 'M3 content',
createdAt: ISODate('2021-01-01T03:00:00.000Z'),
replyTo: ObjectId('53ed7efca75ca1a5248a281a'),
},
children: [
{
_id: ObjectId('53ed80bba75ca1a5248a281b'),
name: 'Person 2',
subject: 'M2 - Reply 1 to M1',
content: 'M2 content',
createdAt: ISODate('2021-01-01T02:00:00.000Z'),
replyTo: ObjectId('53ed7efca75ca1a5248a281a'),
},
{
_id: ObjectId('53ed80bba75ca1a5248a281c'),
name: 'Person 3',
subject: 'M3 - Reply 2 to M1',
content: 'M3 content',
createdAt: ISODate('2021-01-01T03:00:00.000Z'),
replyTo: ObjectId('53ed7efca75ca1a5248a281a'),
},
]
},
{
_id: ObjectId('53ed80bba75ca1a5248a281d'),
name: 'Person 4',
subject: 'M4',
content: 'M4 content',
createdAt: ISODate('2021-01-01T02:30:00.000Z'),
replyTo: null,
latest: {
_id: ObjectId('53ed80bba75ca1a5248a281d'),
name: 'Person 4',
subject: 'M4',
content: 'M4 content',
createdAt: ISODate('2021-01-01T02:30:00.000Z'),
replyTo: null,
},
children: []
},];
Appreciate any help in getting this query sorted. Thanks.
You can use aggregation pipeline stages,
$match replyTo us null condition
$graphLookup to join same collection to get reply messages in children
$addFields to check condition is children is empty then return root document otherwise return last element from children
db.collection.aggregate([
{ $match: { replyTo: null } },
{
"$graphLookup": {
"from": "collection",
"startWith": "$_id",
"connectFromField": "_id",
"connectToField": "replyTo",
"as": "children"
}
},
{
$addFields: {
latest: {
$cond: [
{ $eq: [{ $size: "$children" }, 0] },
"$$ROOT",
{ $arrayElemAt: [{$slice: ["$children", -1]}, 0] }
]
}
}
}
])
Playground
For query optimization you can do last stage $addFields process in your client side.
I am very new to mongoDB and mongoose and I also know questions like this has been already asked but still I didn't get any luck.
So what I am trying to do is I have 2 collections one is products and second is categories and I am trying to get the products that are of category type: fruits
product.model.js
const mongoose = require('mongoose')
const productSchema = new mongoose.Schema({
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Category'
},
name: {
type: String,
required: true,
unique: true
},
price: {
type: Number,
required: true
},
image: {
type: String,
required: true
},
description: {
type: String,
required: true
}
})
const Product = mongoose.model('Product', productSchema)
module.exports = Product
category.model.js
const mongoose = require('mongoose')
const categorySchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
lowercase: true
}
})
const Category = mongoose.model('Category', categorySchema)
module.exports = Category
products collecction
[ { _id: 5ffc9795355f3707ec326f51,
name: 'apple',
price: 80,
image: 'apple1.jpg',
description:
'Do you really need description for this ??',
category: 5ffc94e8a7542a37101a119c,
__v: 0 },
{ _id: 5ffd54409793c33b183376b8,
name: 'Beef',
price: 180,
image: 'beef1.jpg',
description: 'Don\'t you dare to ask about beef in india',
category: 5ffc94dda7542a37101a119b,
__v: 0 },
{ _id: 5ffd54969793c33b183376b9,
name: 'Mango',
price: 100,
image: 'mango1.jpg',
description:
'Have some manog because you cannot eat the bottle of slice like katrina kaif do, its crazy',
category: 5ffc94e8a7542a37101a119c,
__v: 0 } ]
categories collection
[ { _id: 5ffc947ea7542a37101a119a, name: 'vegitables', __v: 0 },
{ _id: 5ffc94dda7542a37101a119b, name: 'non-veg', __v: 0 },
{ _id: 5ffc94e8a7542a37101a119c, name: 'fruits', __v: 0 } ]
Now I want to the get the products whose category are fruits
I know I have to use aggregation and lookup for this I also tried but didn't get any luck, this is my code
const Product = require('./models/product')
const Category = require('./models/category')
const test = async () => {
try {
var query = [
{
$lookup: {
from: "product",
localField: "category",
foreignField: "_id",
as: "product"
}
}]
const productCate = await Product.aggregate(query)
console.log(productCate)
// const productCat = await Product.find().populate({
// path: 'category',
// match: {name: 'fruits'}
// }).exec()
// console.log(productCat)
}catch(e) {
}
}
test()
UPDATE-1
I also tried ppuplate but still didn't get the response as expected, this is my code:
const test = async () => {
try {
const productCat = await Product.find().populate({
path: 'category',
match: {name: 'fruits'}
}).exec()
console.log(productCat)
}catch(e) {
}
}
test()
this is my output
[ { _id: 5ffc9795355f3707ec326f51,
name: 'apple',
price: 80,
image: 'apple1.jpg',
description:
'Do you really need description for this, how dumb are you ??',
category: { _id: 5ffc94e8a7542a37101a119c, name: 'fruits', __v: 0 },
__v: 0 },
{ _id: 5ffd54409793c33b183376b8,
name: 'Beef',
price: 180,
image: 'beef1.jpg',
description: 'Don\'t you dare to ask about beef in india',
category: null,
__v: 0 },
{ _id: 5ffd54969793c33b183376b9,
name: 'Mango',
price: 100,
image: 'mango1.jpg',
description:
'Have some manog because you cannot eat the bottle of slice like katrina kaif do, its crazy',
category: { _id: 5ffc94e8a7542a37101a119c, name: 'fruits', __v: 0 },
__v: 0 } ]
Here I also get the beef that is fall under non-veg category but with the category null. Actually I only want the fruits category products.
you can following this code
const test = async () => {
try {
let categoryId = await Category.findOne({name:"fruits"}).select("_id")
const productCat = await Product.find({category:categoryId}).populate(
"category"
).lean()
console.log(productCat)
}catch(e) {
}
}
test()
you can do with with populate match without using aggregation:
Product.find().populate({
path: 'category',
match: { 'name': 'fruits' }
})
.exec()
I have 3 collections in mongodb generated by strapi.io, I want customize query populate data by mongoose in my project. But i cannot populate data like strapi result.
Category collection:
{
_id: "5d10a731c5077836540bebf0",
posts: [
"5d10a6fbc5077836540bebed",
"5d10af45c5077836540bebf1"
],
name: "Support",
ids: "support",
keywords: "support",
des: "support des",
createdAt: "2019-06-24T10:34:25.383Z",
updatedAt: "2019-06-24T11:08:53.475Z",
__v: 0,
id: "5d10a731c5077836540bebf0"
}
Post collection:
{
_id: "5d10af45c5077836540bebf1",
ids: "test",
title: "this is test",
des: "test",
keywords: "test",
body: "testtesttesttesttest",
createdAt: "2019-06-24T11:08:53.467Z",
updatedAt: "2019-06-24T11:08:53.477Z",
__v: 0,
id: "5d10af45c5077836540bebf1"
}
FileUpload collection:
{
_id: "5d10af45c5077836540bebf2",
name: "THUMBNAIL.png",
sha256: "0bP9PI3R_ygF07cLhg5U-syLeVCz4ZbBrwZZi2OtPL4",
hash: "9f4e8bbd13b94f2baa3d26b335124717",
ext: ".png",
mime: "image/png",
size: "297.33",
url: "/uploads/9f4e8bbd13b94f2baa3d26b335124717.png",
provider: "local",
related:
[
{
_id: "5d10af45c5077836540bebf3",
ref: "5d10af45c5077836540bebf1",
kind: "Post",
field: "pic"
}
],
createdAt: "2019-06-24T11:08:53.501Z",
updatedAt: "2019-06-24T11:08:53.505Z",
__v: 0,
id: "5d10af45c5077836540bebf2"
}
I can populate "posts" on Category model with
Cat.find().populate({path: 'posts',model: 'Post'})
But I can not populate "categories" and "pic" on Post model.
How can I populate "categories" and "pic" like this result of strapi:
{
_id: "5d10af45c5077836540bebf1",
ids: "test",
title: "this is test",
des: "test",
keywords: "test",
body: "testtesttesttesttest",
createdAt: "2019-06-24T11:08:53.467Z",
updatedAt: "2019-06-24T11:08:53.477Z",
__v: 0,
id: "5d10af45c5077836540bebf1",
pic: {
_id: "5d10af45c5077836540bebf2",
name: "THUMBNAIL.png",
sha256: "0bP9PI3R_ygF07cLhg5U-syLeVCz4ZbBrwZZi2OtPL4",
hash: "9f4e8bbd13b94f2baa3d26b335124717",
ext: ".png",
mime: "image/png",
size: "297.33",
url: "/uploads/9f4e8bbd13b94f2baa3d26b335124717.png",
provider: "local",
related: [
"5d10af45c5077836540bebf1"
],
createdAt: "2019-06-24T11:08:53.501Z",
updatedAt: "2019-06-24T11:08:53.505Z",
__v: 0,
id: "5d10af45c5077836540bebf2"
},
categories:
[
{
posts: [
"5d10a6fbc5077836540bebed",
"5d10af45c5077836540bebf1"
],
_id: "5d10a731c5077836540bebf0",
name: "Support",
ids: "support",
keywords: "support",
des: "support des",
createdAt: "2019-06-24T10:34:25.383Z",
updatedAt: "2019-06-24T11:08:53.475Z",
__v: 0,
id: "5d10a731c5077836540bebf0"
}
]
}
you have to create another collection inside the post. as like you have an independent collection then you can populate. for example :
Post: {body: ,title: ,Image : { image: {name : , etc }}}
this can be a collection inside collection. the above code is not correct you have to mention your own fields.