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

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

Related

Javascript Object transformation/flat

My goal is to use create schema for json-schema-yup-transformer, therefore, I need to get this format :
const schema = {
type: "object",
properties: {
firstName: {
type: "string",
minLength: 2,
},
email: {
type: "string",
format: "email",
},
},
required: requiredFields,
};
I've got a schemaProperties :
const schemaProperties = formatData.map((item) => {
return {
[item.value]: { type: item.type, validation: item.validation },
};
});
That returns me :
[
{
"firstName": {
"type": "text",
"validation": {
"required": true,
"requiredMessage": "Prénom requis"
}
}
},
{
"lastName": {
"type": "text"
}
},
...
]
But, my problem is that schemaProperties is an array actually and not an object. I tried to destruct it and transform into an object, but its not working... Im sure its not something very complicated but I'm stuck...

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"
}
}
]

Mongo Aggregation problem, want to avoid outter wrapper

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,
},
},
},
},
]);

Update MongoDB object in object by id

Model:
const projectSchema = new Schema({
name: {
type: String,
maxlength: 50
},
description: {
type: String
},
projectLead: {
type: String
},
start: {
type: String
},
end: {
type: String
},
projectType: {
type: String
},
claimId: {
type: String
},
organization: {
type: String
},
seats: [{
id: String,
employee: String,
role: String,
start: String,
end: String,
workload: Number,
skills: Array,
approved: Boolean
}]
}, {
timestamps: true
})
Model response example:
{
"project": {
"_id": "5cab4b9bc9b29a7ba2363875",
"name": "Project Title",
"description": "Project description",
"projectLead": "email#email",
"start": "2018-06-01T09:45:00.000Z",
"end": "2019-06-31T09:45:00.000Z",
"claimId": "AIIIIII",
"organization": "Company ACE",
"seats": [
{
"skills": [
"Node.js",
"Vue.js"
],
"_id": "5cab548e5cefe27ef82ca313",
"start": "2018-06-01T09:45:00.000Z",
"end": "2019-06-31T09:45:00.000Z",
"role": "Developer",
"approved": false,
"workload": 20,
"employee": ''
}
],
"createdAt": "2019-04-08T13:24:43.253Z",
"updatedAt": "2019-04-08T14:02:54.257Z",
"__v": 0
}
}
Controller:
exports.updateSeatEmployee = async (req, res, next) => {
try {
const project = await Project.findOneAndUpdate({
"seats._id": req.params.id
}, {
"seats.employee": req.body.employee
}, {
new: true
})
console.log("project", project);
return res.json({
project: project
})
} catch (error) {
next(error)
}
}
Debugger:
Mongoose: users.createIndex({ email: 1 }, { unique: true, background:
true }) { sub: '5cab48ebec24577ab3329fcd', iat: 1554729210 }
Mongoose: users.findOne({ _id: ObjectId("5cab48ebec24577ab3329fcd") },
{ projection: {} })
Mongoose: projects.findAndModify({ 'seats._id':
ObjectId("5cab529bcafa027e30ee229c") }, [], { '$setOnInsert': {
createdAt: new Date("Mon, 08 Apr 2019 14:45:56 GMT") }, '$set': {
'seats.$.employee': 'email#email.com', updatedAt: new
Date("Mon, 08 Apr 2019 14:45:56 GMT") } }, { new: true, upsert: false,
remove: false, projection: {} }) (node:33302) DeprecationWarning:
collection.findAndModify is deprecated. Use findOneAndUpdate,
findOneAndReplace or findOneAndDelete instead.
project null
I want to search for a specific object in seats by its id.
This specific seat should be update. In my case I want to update the employee field.
If I do a findOne({"seats._id": req.params.id}) I get the project back but findOneAndUpdate returns null.
You need the $ positional operator since seats is an array and you should use $set operator if you want to update just one field
const project = await Project.findOneAndUpdate({
"seats._id": req.params.id
}, {
$set: { "seats.$.employee": req.body.employee }
}

Categories

Resources