Strapi mongodb project specific fields in embedded documents - mongodb

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

Related

MongoDB aggregate data using $agg

So i try to aggregate the data from mongoDB using $match and $group to get the exact value an d format with data from mongoDB in JSON as Below:
[ {
_id: new ObjectId("6357b4237cf79bba3e66c096"),
userId: new ObjectId("635762fe85b94eac7466d965"),
formId: new ObjectId("6357921d49de88bb7fffcfe4"),
title: 'Quality',
username: 'Jansenstan24#gmail.coms',
date: '2022-10-25',
answer: {
'6357921d49de88bb7fffcfe8': 'john#nabatisnack.com',
Text: 'john#nabatisnack.com',
'6357b331235053a9d4e8d037': 'john#dose.com',
Email: 'john#dose.com',
'6357b335235053a9d4e8d03a': 'Maja',
Plant: 'Maja'
},
createdAt: 1666692131,
updatedAt: 1666692131,
__v: 0
},
{
_id: new ObjectId("6357b54922866fae378af370"),
userId: new ObjectId("635762fe85b94eac7466d965"),
formId: new ObjectId("6357921d49de88bb7fffcfe4"),
title: 'Quality',
username: 'Jansenstan24#gmail.coms',
date: '2022-10-25',
answer: {
'6357921d49de88bb7fffcfe8': 'john#dose.com',
Text: 'john#dose.com',
'6357b331235053a9d4e8d037': 'john#nabatisnack.com',
Email: 'john#nabatisnack.com',
'6357b335235053a9d4e8d03a': 'Cica',
Plant: 'Cica'
},
createdAt: 1666692425,
updatedAt: 1666692425,
__v: 0
},
{
_id: new ObjectId("6357b6a2a13ab3c4a462be8f"),
userId: new ObjectId("635647c1e24d0a4482e3c0a9"),
formId: new ObjectId("6357921d49de88bb7fffcfe4"),
title: 'Quality',
username: 'adam#wegodev.com',
date: '2022-10-25',
answer: {
'6357921d49de88bb7fffcfe8': '12',
Text: '12',
'6357b331235053a9d4e8d037': 'john#dose.coms',
Email: 'john#dose.coms',
'6357b335235053a9d4e8d03a': 'Ranca',
Plant: 'Ranca'
},
createdAt: 1666692770,
updatedAt: 1666692770,
__v: 0
}]
using this line of code in javascript:
forms = await Answer.aggregate([
{
$match: { title: "Quality" },
},
{ $group: { title: "Quality"} },
]);
what i expected is the result like this:
{
formId: new ObjectId("6357921d49de88bb7fffcfe4"),
title: 'Quality',
username: [{'Jansenstan24#gmail.coms',adam#wegodev.com}]
date: [{'2022-10-25','2022-10-26}]
answer: [{
'6357921d49de88bb7fffcfe8': 'john#nabatisnack.com',
Text: 'john#nabatisnack.com',
'6357b331235053a9d4e8d037': 'john#dose.com',
Email: 'john#dose.com',
'6357b335235053a9d4e8d03a': 'Maja',
Plant: 'Maja'
},{
'6357921d49de88bb7fffcfe8': 'john#dose.com',
Text: 'john#dose.com',
'6357b331235053a9d4e8d037': 'john#nabatisnack.com',
Email: 'john#nabatisnack.com',
'6357b335235053a9d4e8d03a': 'Cica',
Plant: 'Cica'
},...etc],
},
i try to use more complex query but it seems it not return the result i want and i've try to seek any related problem but it wont return the same result as i want
You have the right idea using $group, you just need to leverage it's syntax properly, like so:
db.collection.aggregate([
{
$match: {
title: "Quality"
}
},
{
$group: {
_id: "$title",
title: {
$first: "$title"
},
username: {
"$addToSet": "$username"
},
date: {
$addToSet: "$date"
},
formId: {
$addToSet: "$formId"
},
answer: {
$push: "$answer"
}
}
}
])
Mongo Playground

How to get a field of an object in document?

I am not sure how to phrase this question properly but basically I have an "Order" Schema and each order model contains an array of product objects created using "Product" Schema
When I create an order, my req.body is this
body: {
orderItems: [ [Object] ],
shippingAddress: {
fullName: '123',
address: '1231',
city: '123',
postalCode: '123',
country: '123'
},
shippingPrice: 0,
paymentMethod: 'Stripe',
itemsPrice: 338,
totalPrice: 338
},
If I log req.body.orderItems, I can see each product object printed
{
_id: new ObjectId("62d51a3895cad3ca283302f3"),
name: 'Christmas Cake',
slug: 'christmas-cake',
image: '/images/cake.jpg',
shop: 'Custom Cakes',
category: 'food',
description: 'Custom baked christmas cake, pre-order needed.',
price: 70,
stock: 1,
rating: 3,
numReviews: 2,
__v: 2,
createdAt: 2022-07-18T08:30:48.931Z,
updatedAt: 2022-07-20T03:03:00.592Z,
}
{
_id: new ObjectId("62d7a8c126dcacfc13055e3d"),
name: 'cake',
slug: 'cake',
image: '/images/cake.jpg',
shop: 'Custom Cakes',
category: 'food',
description: 'cake',
price: 15,
stock: 2,
rating: 0,
numReviews: 0,
user: { _id: new ObjectId("62d51d57c08cd7e6675e8d45")},
reviews: [],
createdAt: 2022-07-20T07:03:29.372Z,
updatedAt: 2022-07-20T07:03:59.315Z,
__v: 0
}
But I am unable to obtain the 'shop' field. req.body.orderItems.shop returns undefined

mongodb pull function why not working in my situation?

i make simple board app. but i face scrab problem.
i want to pull data in scrabContent when people unscrab. but it doesnt' work. help me plz..
My Schema looks like this. scrabContent means contents that i scrab. So, when i scrab some contents, they are stored in scrabContent.
const userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
name: {
type: String,
required:true,
unique: true,
},
follower : [String],
following : [String],
boardBookmark: [],
scrabContent: [],
songs: [],
songsView: {
type: Number,
default :0,
},
profileImage: {
type: String,
}
});
this is schema data example.
{
follower: [],
following: [],
boardBookmark: [
{
name: 'asd',
introduction: 'dsadad',
boardId: '603a4e485d99d993e0bfdfee'
}
],
scrabContent: [
{
commentsNum: 3,
likes: [],
image: [Array],
isDeleted: false,
_id: 603b67e1904622ca9ee2cddb,
title: 'ㄴㅁㅇㄹㅁㄴㄹㅁ',
content: 'ㅁㅇㄴㄹㅁㄹㅁㄴㄹㅁㄴㄹ',
postUser: 'umpa',
postUserId: 603751786587acfbf1052d34,
boardId: 603a4e485d99d993e0bfdfee,
time: '2021/02/28 18:52:32',
__v: 0
},
{
commentsNum: 5,
likes: [Array],
image: [Array],
isDeleted: false,
_id: 603b09f509dcb8b594c1f015,
title: '테스트',
content: 'ㅋㅋ',
postUser: 'umpa',
postUserId: 603751786587acfbf1052d34,
boardId: 603a4e485d99d993e0bfdfee,
time: '2021/02/28 12:11:47',
__v: 0
}
],
songs: [
{
id: '1469319400',
type: 'songs',
href: '/v1/catalog/kr/songs/1469319400',
attributes: [Object],
name: 'LOVE AGAIN'
},
{
id: '1265893529',
type: 'songs',
href: '/v1/catalog/kr/songs/1265893529',
attributes: [Object],
name: 'Get You (feat. Kali Uchis)'
},
{
id: '1265893532',
type: 'songs',
href: '/v1/catalog/kr/songs/1265893532',
attributes: [Object],
name: 'Best Part (feat. H.E.R.)'
},
{
id: '1356070221',
type: 'songs',
href: '/v1/catalog/kr/songs/1356070221',
attributes: [Object],
name: 'Daniel'
},
{
id: '1438474485',
type: 'songs',
href: '/v1/catalog/kr/songs/1438474485',
attributes: [Object],
name: 'Falling'
}
],
songsView: 0,
_id: 603a84d9760444a652d2cc72,
email: 'test',
password: '$2b$10$w8b85O6KQwGIZ0D1x0TGle.qofoEC43OKI5cMSf7tfqld12fSUWlu',
name: 'test',
__v: 0
}
and this is server code to pull. req.user._id means User Schema's _id(in this case: 603a84d9760444a652d2cc72). and req.params.id means Content _id(in this case: 603b67e1904622ca9ee2cddb) in ScrabContent.
router.delete('/deleteScrabContent/:id', requireAuth, async (req, res) => {
try {
await User.findOneAndUpdate({_id: req.user._id}, {$pull: {scrabContent: {_id: req.params.id}}}, {new: true});
} catch (err) {
return res.status(422).send(err.message);
}
});
i don't know why scrabContent doesn't work.. help me T^T

How to get this parent child query data in Mongo DB

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.

Mongoose: Get the data from 2 collections, like get products that have same category type like fruits

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()