MongoDB nested search query parameters - javascript

Is there a chance I can query the MongoDB record using findOneAndUpdate, or findByIdAndUpdate by triggering the record by the "ID" and "lang" fields? Here is the database object sample:
{
"id": "61842e6fb19afbc0922f5505",
"locales": [
{
"lang": "ru",
"title": "Тестовый десерт",
"description": "тестовый"
},
{
"lang": "lv",
"title": "Testu deserts",
"description": "Testu descriptions"
},
{
"lang": "en",
"title": "Test dessert",
"description": "Test description"
}
]
}
And this is how I attempt to trigger, and it doesn't work:
const filter = {
_id: id,
locales: {
lang: lang
}
}
const product = await Product.findOneAndUpdate(filter, {
lang: {
title,
description,
price
}
}, { new: true });

You can use the $set operator like that:
const product = await Product.findOneAndUpdate({
_id: "61842e6fb19afbc0922f5505",
"locales.lang": "ru"
},
{
"$set": {
"locales.$": {
lang: "ru",
title: "title",
description: "desription",
price: 23
}
}
})
Working playground: https://mongoplayground.net/p/oBNS6wtK50g

Related

How to remove deeply nested object (Node.js, mongoose)

I'm making a kanban task management app and I'm trying to remove a task with the _id: req.params.id which has the value of 62fa5ae05778ec97bc6ee23a. I tried the following:
const task = await Board.findOneAndUpdate(
{
"columns.tasks._id": req.params.id,
},
{ $pull: { "columns.$.tasks.$._id": req.params.id } },
{ new: true }
);
But I get the error Too many positional (i.e. '$') elements found in path'columns.$.tasks.$._id'
I searched for a while and came across arrayFilters from the docs but I'm struggling a lot to understand how to implement it for this particular need.
{
"_id": "62fa5aa25778ec97bc6ee231",
"user": "62f0eb5ebebd0f236abcaf9d",
"name": "Marketing Plan",
"columns": [
{
"name": "todo",
"_id": "62fa5aa25778ec97bc6ee233",
"tasks": [
{
"title": "Task Four",
"description": "This is task four",
"subtasks": [
{
"name": "wash dshes",
"completed": false,
"_id": "62fa5ae05778ec97bc6ee23b"
},
{
"name": "do homework",
"completed": false,
"_id": "62fa5ae05778ec97bc6ee23c"
}
],
"_id": "62fa5ae05778ec97bc6ee23a"
}
]
},
{
"name": "doing",
"_id": "62fa5aa25778ec97bc6ee234",
"tasks": []
},
{
"name": "done",
"_id": "62fa5aa25778ec97bc6ee235",
"tasks": []
}
],
"__v": 0
}
You need to use $[] positional operator in order to pull from the nested array. Try running this query:
db.Board.updateOne({
"_id" : "62fa5aa25778ec97bc6ee231",
}, {
$pull: { 'columns.$[].tasks': { '_id': '62fa5ae05778ec97bc6ee23a' } }
});

Issue while updating nested data createEntityAdapter RTK query

I am working on the chat that is utilising RTK Query with entity adapters. We created nested normalised createEntityAdapter . I want to update the message key from onCacheEntryAdded, but not able to update nested object. I'm attaching the query endpoint code along with sample response.
RTK Query Endpoint
endpoints: builder => ({
getMessages: builder.query({
query: ({ orderId, userId, channel }) => {
return {
url: `/messages?orderId=${orderId}&userId=${userId}`,
method: 'GET',
}
},
transformResponse(response, meta, arg) {
return messagesAdapter.setAll(messagesAdapter.getInitialState(), [
{
id: `${arg.orderId}-${arg.userId}`,
isTyping: false,
channel: arg.channel,
orderId: arg.orderId,
messages: messagesAdapter.addMany(
messagesAdapter.getInitialState(),
response,
),
},
])
},
async onCacheEntryAdded(
arg,
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved, cacheData },
) {
try {
await cacheDataLoaded
updateCachedData(draft => {
messagesAdapter.updateOne(draft, {
id: '62d529f60be7549be1f53df3-62d64eef37d10fea52e1ce72',
changes: {
messages: messagesAdapter.updateOne(
messagesAdapter.getInitialState(),
{
id: '62da7221bc0eb3a259fc2256',
changes: {
message: 'updated message',
},
},
),
},
})
})
} catch {
// no-op in case `cacheEntryRemoved` resolves before `cacheDataLoaded`,
// in which case `cacheDataLoaded` will throw
}
await cacheEntryRemoved
},
providesTags: (result, error, arg) => {
console.log('providesTags', result, error, arg)
return ['chat']
},
}),
}),
Sample response
{
"ids": [
"62d529f60be7549be1f53df3-62d64eef37d10fea52e1ce72"
],
"entities": {
"62d529f60be7549be1f53df3-62d64eef37d10fea52e1ce72": {
"id": "62d529f60be7549be1f53df3-62d64eef37d10fea52e1ce72",
"isTyping": false,
"channel": "62d7d9266599a9f0c3bcdaba",
"orderId": "62d529f60be7549be1f53df3",
"messages": {
"ids": [
"62da7221bc0eb3a259fc2256",
"62da724dbc0eb3a259fc2260",
"62da75559f7a23f89a0958d4",
"62da94e59f7a23f89a0958ed"
],
"entities": {
"62da7221bc0eb3a259fc2256": {
"order": "62d529f60be7549be1f53df3",
"alias": "Jacques82",
"sender": "62d7999d976791c65dd6eacd",
"senderRole": "ops",
"receiver": "62d64eef37d10fea52e1ce72",
"receiverRole": "student",
"receiverAlias": "Daniela_Jacobs0",
"message": "dsds",
"sentAt": "2022-07-22T09:47:13.000Z",
"id": "62da7221bc0eb3a259fc2256"
},
"62da724dbc0eb3a259fc2260": {
"order": "62d529f60be7549be1f53df3",
"alias": "Jacques82",
"sender": "62d7999d976791c65dd6eacd",
"senderRole": "ops",
"receiver": "62d64eef37d10fea52e1ce72",
"receiverRole": "student",
"receiverAlias": "Daniela_Jacobs0",
"message": "hello nm",
"sentAt": "2022-07-22T09:47:57.000Z",
"id": "62da724dbc0eb3a259fc2260"
},
"62da75559f7a23f89a0958d4": {
"order": "62d529f60be7549be1f53df3",
"alias": "Jacques82",
"sender": "62d7999d976791c65dd6eacd",
"senderRole": "ops",
"receiver": "62d64eef37d10fea52e1ce72",
"receiverRole": "student",
"receiverAlias": "Daniela_Jacobs0",
"message": "b",
"sentAt": "2022-07-22T10:00:53.000Z",
"id": "62da75559f7a23f89a0958d4"
},
"62da94e59f7a23f89a0958ed": {
"order": "62d529f60be7549be1f53df3",
"alias": "Jacques82",
"sender": "62d7999d976791c65dd6eacd",
"senderRole": "ops",
"receiver": "62d64eef37d10fea52e1ce72",
"receiverRole": "student",
"receiverAlias": "Daniela_Jacobs0",
"message": "hello there",
"sentAt": "2022-07-22T12:15:31.000Z",
"id": "62da94e59f7a23f89a0958ed"
}
}
}
}
}
}

How to lookup a field with an array in nested subdocument mongodb?

I am trying to retrieve some lookup data for an embedded array in a document.
Here is a sample of the data:
{
"_id": "58a4fa0e24180825b05e14e9",
"fullname": "Test User",
"username": "testuser"
"teamInfo": {
"challenges": [
{
"levelId": "5e14e958a4fa0",
"title": "test challenge 1.1"
},
{
"levelId": "5e14e958a4fa0",
"title": "test challenge 1.2"
},
{
"levelId": "5e14e958a4fa1",
"title": "test challenge 2.1"
}
]
}
}
As you see, teamInfo.challenges is an array, containing levelId fields. These are pointing to the _id field in another collection called levels.
But how can I do to getting json response like this?
{
"_id": "58a4fa0e24180825b05e14e9",
"fullname": "Test User",
"username": "testuser"
"teamInfo": {
"challenges": [
{
"levelInfo": {
"name": "Level 1"
},
"title": "test challenge 1.1"
},
{
"levelInfo": {
"name": "Level 1"
},
"title": "test challenge 1.2"
},
{
"levelInfo": {
"name": "Level 2"
},
"title": "test challenge 2.1"
}
]
}
}
Im trying using unwind, project, and group. But im so confused.
const user = await User.aggregate([
{
$match: {_id: new mongoose.Types.ObjectId(req.user.userId)}
},
{
$lookup: {
from: 'levels',
localField: 'teamInfo.challenges.levelId',
foreignField: '_id',
as: 'challLevelInfo'
}
},
{
$group: {
_id: "$_id",
........IM CONFUSED HERE........
}
}
]);
You can use lookup pipeline to handle nested lookup
const pipeline = [
{
$match: {_id: new mongoose.Types.ObjectId(req.user.userId)}
},
{
$lookup: {
from: 'levels',
let: { level_id: "$teamInfo.challenges.levelId" },
pipeline: [
{
$match: {
$expr: {
$eq: ["$_id", "$$level_id"]
}
}
},
{
$lookup: {
from: '<level collection>',
localField: "levelId",
foreignField: "_id",
as: "levelInfo"
}
},
{
$project: {
levelInfo: {
name: "$levelInfo.name"
}
title: 1
}
}
],
as: "challenges"
},
},
{ $project: {
_id: 1,
fullname: 1,
username: 1,
teamInfo: {
challenges: "$challenges"
}
}}
]
const result = await User.Aggregate(pipeline)
hope this help !

How to show a nested object as a super object in MongoDB?

As it is stated here, I had to save reference objects inside of a nested key called 'item';
var userSchema = new Schema({
name: String,
connections: [{
kind: String,
item: { type: ObjectId, refPath: 'connections.kind' }
}]
});
var organizationSchema = new Schema({ name: String, kind: String });
var User = mongoose.model('User', userSchema);
var Organization = mongoose.model('Organization', organizationSchema);
In my DB, it is more like this:
var childSchema = new Schema({
kind: String,
item: {
type: Schema.Types.ObjectId,
refPath: 'children.kind'
}
},{ _id : false, strict:false });
var schema = new Schema({
name: String,
kind: String,
children: [childSchema]
},{
strict: false
});
Now, it is a tree based folder structure model, and it can have either a Folder or a Leaf as child object.
I needed a recursive populate, so I find an answer on SO, it became like this;
var autoPopulateChildren = function(next) {
this.populate({path:'children.item', select:'name id children'});
next();
};
schema.pre('findOne', autoPopulateChildren)
.pre('find', autoPopulateChildren)
Now, when I make a find query, I get this-like example;
{
"name": "Some Folder",
"children": [
{
"kind": "Leaf",
"item": {
"name": "First Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
}
},
{
"kind": "Folder",
"item": {
"name": "First Level Folder",
"id": "5b61d844d77fb30b9537e5d1"
"children": [
{
"kind": "Leaf",
"item": {
"name": "Second Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
}
}
]
}
}
],
"id": "5b61c85f25375fddf6048d3d"
}
But now, I need to get rid of 'kind' (don't show) and also I need to show 'item' object as a child (it should be name instead of item:{name:'a'}:
{
"name": "Some Folder",
"children": [
{
"name": "First Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
},
{
"name": "First Level Folder",
"id": "5b61d844d77fb30b9537e5d1"
"children": [
{
"name": "Second Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
}
]
}
],
"id": "5b61c85f25375fddf6048d3d"
}
How can I do this on autoPopulateChildren function?

unable to populate articles in mongoose [duplicate]

This question already has answers here:
How to convert string to objectId in LocalField for $lookup Mongodb [duplicate]
(1 answer)
Querying after populate in Mongoose
(6 answers)
Closed 4 years ago.
I have the category schema like this:
var category_article_Schema = new Schema({
"article_id": { type: String, required: false, unique: false },
"category": String,
"articles": [{ type: mongoose.Schema.Types.ObjectId, ref:'article'}],
});
var category_article_Schema = mongoose.model('category_article_Schema', category_article_Schema);
module.exports = category_article_Schema;
Article schema:
var articleSchema = new Schema({
"title": { type: String, required: true, unique: false },
"details": String,
"username": { type: String, required: true, unique: false },
"postImageUrl": String,
"url": String,
"categories": [String],
"created_at": { type: Date, default: Date.now }
});
var article = mongoose.model('article', articleSchema);
module.exports = article;
When I try to populate articles in the below function, I get only category id and name but no articles populated.
function getPostByCategory(req, res, next) {
category_article_model.find({category: req.params.name}) //sports
.populate('articles')
.exec()
.then(function(articlesByCategory) {
console.log(articlesByCategory);
})
.catch(function(err){
console.log('err ', err);
})
}
All the data I have in article collection is this:
`{
"_id": {
"$oid": "5b0008ce8787890004989df1"
},
"categories": [
"sports",
"health"
],
"title": "sample",
"details": "sample ",
"created_at": {
"$date": "2018-05-19T11:21:50.837Z"
},
"__v": 0
},
{
"_id": {
"$oid": "5b0087646dda9600049a9a27"
},
"categories": [
"sports"
],
"title": "sample3333",
"details": " sample3333",
"created_at": {
"$date": "2018-05-19T20:21:56.126Z"
},
"__v": 0
}`
And category_article_schema collection has:
{
"_id": {
"$oid": "5b0087646dda9600049a9a28"
},
"category": "sports",
"article_id": "5b0087646dda9600049a9a27",
"__v": 0
}
But the data returned is empty array of article:
[ { articles: [],
_id: 5b0008ce8787890004989df2,
category: 'sports',
article_id: '5b0008ce8787890004989df1',
__v: 0 } ]
I am not sure what could be the issue?

Categories

Resources