Mongo Aggregation problem, want to avoid outter wrapper - javascript

my goal is to update the active property within the weeks object, instead i get another object wrapper.
How i can either avoid this behavior or rewrite the aggregation to get the values from the weeks object in the wrapper?
{
"weeks": {
"time": [
"06",
"00"
],
"active": true,
"reason": "",
"bookTime": 202102260600,
"qdate": 20210226,
"booked": false
},
"active": false
},
]
My aggregation pipeline:
const company = await Company.aggregate([
{ $match: { email: 'test#gmail.com' } },
{ $unwind: '$weeks' },
{ $match: { 'weeks.qdate': { $gte: 20210226, $lte: 20210305 } } },
{ $unset: '_id' },
{
$project: {
weeks: 1,
active: {
$cond: {
if: { $lt: ['$weeks.bookTime', 202102261445] },
then: false,
else: true,
},
},
},
},
]);

I forgot that i need to add the $ sign on nested objects.
So the final pipeline will look like this.
const company = await Company.aggregate([
{ $match: { email: 'test#gmail.com' } },
{ $unwind: '$weeks' },
{ $match: { 'weeks.qdate': { $gte: 20210226, $lte: 20210305 } } },
{ $unset: '_id' },
// { $group: { _id: { time: '$weeks.bookTime' } } },
{
$project: {
bookTime: '$weeks.bookTime',
utc: '$weeks.utc',
booked: '$weeks.booked',
active: {
$cond: {
if: { $lt: ['$weeks.bookTime', 202102261445] },
then: false,
else: true,
},
},
},
},
]);

Related

Mongoose, updated nested array

My question is:
How can I query in the nested arrays?
I want to change value in key "likeUp" which is nested inside object in array "usersWhoLiked". Where "usersWhoLiked" is nested in array "comments"
How Can I do that with mongoose ?
Request that I wrote beneath... do not work, but is very similar to answer given in StackOverflow post: Mongoose update update nested object inside an array
This is my request to db with updateOne:
try {
const response = await Comments.updateOne(
{
productId,
comments: { $elemMatch: { usersWhoLiked: { $elemMatch: { userId } } } },
},
{
$set: { 'comments.$[outer].usersWhoLiked.$[inner].likeUp': likes.up },
},
{
arrayFilters: [{ 'outer._id': commentId }, { 'inner._userId': userId }],
}
).exec();
return res.status(201).json({ response });
} catch (err) {
console.log(err);
return res.send(err);
}
This is the collection, that I am trying to update:
{
"_id": {
"$oid": "6307569d2308b78b378cc802"
},
"productId": "629da4b6634d5d11a859d729",
"comments": [
{
"userId": "62f29c2c324f4778dff443f6",
"userName": "User",
"date": "2022.08.25",
"confirmed": true,
"likes": {
"up": 0,
"down": 0
},
"content": {
"rating": 5,
"description": "Nowy komentarz"
},
"_id": {
"$oid": "630756b22308b78b378cc809"
},
"usersWhoLiked": [
{
"userId": "62f29c2c324f4778dff443f1",
"likeUp": true,
"_id": {
"$oid": "6307572d2308b78b378cc80e"
}
},
{
"userId": "62f29c2c324f4778dff443f2",
"likeUp": true,
"_id": {
"$oid": "6307572d2308b78b378cc80c"
}
}
]
}
],
"__v": 0
}
Mongooes schema for comment collection:
const commentSchema = new Schema({
productId: String,
comments: [
{
userId: String,
userName: String,
date: String,
confirmed: Boolean,
likes: {
up: {
type: Number,
default: 0,
},
down: {
type: Number,
default: 0,
},
},
content: {
rating: Number,
description: String,
},
usersWhoLiked: [{ userId: String, likeUp: Boolean }],
},
],
});
I guess the problem is with your arrayFilters operator, because you are trying to filter by field _userId which does not exist:
arrayFilters: [{ 'outer._id': commentId }, { 'inner._userId': userId }],
I managed to update the likeUp value using the following query:
db.collection.update({
_id: ObjectId("6307569d2308b78b378cc802")
},
{
$set: {
"comments.$[user].usersWhoLiked.$[like].likeUp": false
}
},
{
arrayFilters: [
{
"user._id": ObjectId("630756b22308b78b378cc809")
},
{
"like.userId": "62f29c2c324f4778dff443f1"
}
]
})
Try it on MongoDB playground: https://mongoplayground.net/p/XhQMNBgEdhp

Retrieving a relationship field in mongodb aggregation

I am using mongodb aggregation with a collection named files
that has a relationship with another collection named file_upload.
files = {
type: String,
media: { type: Schema.Types.ObjectId, ref: 'file_upload', required: true },
}
file_upoad = {
name: String,
}
This is the query
const data = await strapi.query('files').model.aggregate([
{
$lookup: {
from: "analytics",
localField: "_id",
foreignField: "file_id",
as: "hits",
}
},
{ $unwind: '$hits' },
{ $group: { _id: "$_id", hitsCount: { $sum: 1 } } },
{ $sort: { hitsCount: -1 } },
{ $limit: 1 },
])
my goal is to retrieve the media as part of the result since it is a relationship field, at the moment I get this
[
{
"_id": "61fd74367b6ee77b89bae34d",
"hitsCount": 12
},
{
"_id": "61fd74367b6ee77b89sddfee",
"hitsCount": 8
}
]
expected result
[
{
"_id": "61fd74367b6ee77b89bae34d",
"hitsCount": 12,
"media": {
name:"name1"
}
},
{
"_id": "61fd74367b6ee77b89sddfee",
"hitsCount": 8,
"media": {
name:"name2"
}
}
]

MongooseJS: How to remove 1 object inside Array in Array of Objects

Hi MongooseJS experts!
I'm new in MongooseJS, This is my 2nd day of solving this problem but I can't find a working solution to this.
Thank you in advance!
My Delete method
Cart.updateOne(
{ "content.merchantId": req.body.merchantId },
{ $pull: { "content.items._id": req.body.productId } },
{ new: true },
function (error, result) {
if (error) { }
else if (result) { }
}
);
Schema
const CartSchema = new Schema({
customerId: {
type: String,
required: true,
},
content: {
merchantName: {
type: String,
required: true,
},
merchantId: {
type: String,
required: true,
},
items: [],
},
});
Sample JSON
[
{
"content": {
"merchantName": "SAMPLE_MERCHANT_NAME",
"merchantId": "SAMPLE_MERCHANT_ID",
"items": [
{
"_id": "SAMPLE_ID",
"title": "SAMPLE TITLE",
}
]
},
"_id": "618220e83966345ab5d451cd",
"__v": 0
},
]
Error message
Cannot use the part (_id) of (content.items._id) to traverse the element ({items: [{ _id: "SAMPLE_ID", title: "SAMPLE TITLE"}] })
you should use like this
db.collection.update({
"content.merchantId": "SAMPLE_MERCHANT_ID"
},
{
$pull: {
"content.items": {
"_id": "SAMPLE_ID"
}
}
},
{
new:true
},
)
https://mongoplayground.net/p/Ou26tab2mBU

Destructure arrays within the MongoDB aggregation pipeline

I was wondering if it was possible to destructure arrays while I am still in the MongoDB aggregation pipeline which would make my code alot neater.
For example, I have the following aggregation pipeline.
await User.aggregate([
{ $match: { _id: userID } },
{
$project: { chatLogs: 1, username: 1, profilePicURL: 1 },
},
{ $unwind: "$chatLogs" },
{
$lookup: {
from: "users",
let: { recipientID: "$chatLogs.recipientID" },
pipeline: [
{
$match: { $expr: { $eq: ["$_id", "$$recipientID"] } },
},
{ $project: { profilePicURL: 1 } },
],
as: "chatLogs.recipientID",
},
},
]);
This gives the following results when queried:
{
"_id": "5f2ffb54eea9c2180a732afa",
"username": "joe",
"profilePicURL": "/images/profile/default_profile.png",
"chatLogs": {
"recipientID": [
{
"_id": "5f2faf5ad18a76073729f475",
"profilePicURL": "/images/profile/default_profile.png"
}
],
"chat": "5f30b6c3d117441c2abda1ba"
}
}
In my case, because "recipientID" represents a default MongoDB id, it will always be unique. Hence I would prefer the following, where the resulting recipientID field is no longer a meaningless array
Desired results:
{
"_id": "5f2ffb54eea9c2180a732afa",
"username": "joe",
"profilePicURL": "/images/profile/default_profile.png",
"chatLogs": {
"recipientID": {
"_id": "5f2faf5ad18a76073729f475",
"profilePicURL": "/images/profile/default_profile.png"
}
"chat": "5f30b6c3d117441c2abda1ba"
}
}
You can deconstruct recipientID array using $unwind in last pipeline,
await User.aggregate([
... // your all pipelines
// add this line
{ $unwind: "$chatLogs.recipientID" }
]);

Mongo DB (node js) group by dates and sum values of unique ids

I have the following documents in my collection:
{
"_id": ObjectId("5b8fed64b77d7829788ebdc8"),
"valueId": "6e01c881-c15e-b754-43bd-0fe7381cc02a",
"value": 14,
"date": "2018-09-05T14:51:11.427Z"
}
I want to group the "date" by a certain interval, get for all "valueId" a sum of the "value", which is inside the date interval. My current aggregation looks like this:
myCollection.aggregate([
{
$match: {
date: {
$gte: start,
$lte: end,
},
},
},
{
$group: {
_id: {
$toDate: {
$subtract: [{ $toLong: '$date' }, { $mod: [{ $toLong: '$date' }, interval] }],
},
},
valueId: { $addToSet: '$valueId' },
},
},
{
$project: {
_id: 1,
valueId: 1,
},
},
]);
Which gives out something like this:
{
_id: 2018-09-04T15:45:00.000Z,
valueId:[
'cb255343-9c16-f495-9c29-3697d6c7d6cb',
'97e729aa-7b0f-c107-d591-01188b768a7a'
]
}
How can I get it to something like this (simplified with one value):
{
_id: 2018-09-04T15:45:00.000Z,
valueId: [[
'cb255343-9c16-f495-9c29-3697d6c7d6cb',
<sum of value>
]]
}
EDIT:
Endsolution:
myCollection.aggregate([
{"$match":{"date":{"$gte":start,"$lte":end}}},
{"$group":{
"_id":{
"interval":{"$toDate":{"$subtract":[{"$toLong":"$date"},{"$mod":[{"$toLong":"$date"},interval]}]}},
"valueId":"$valueId"
},
"value":{"$sum":"$value"}
}},
{ $group: {
_id: "$_id.interval",
values: {
$addToSet: { id: "$_id.valueId", sum: "$value" },}
}}])
You can use multiple group, one for summing value for each valueid and interval combination and second group to push all the documents for interval.
myCollection.aggregate([
{"$match":{"date":{"$gte":start,"$lte":end}}},
{"$group":{
"_id":{
"interval":{"$toDate":{"$subtract":[{"$toLong":"$date"},{"$mod":[{"$toLong":"$date"},interval]}]}},
"valueId":"$valueId"
},
"value":{"$sum":"$value"}
}},
{"$group":{
"_id":"$_id.interval",
"valueId":{"$push":{"id":"$_id.valueId","sum":"$value"}}
}}
])

Categories

Resources