How to delete an element in a sub sub document mongoosejs - javascript

how to delete the "extras" with "id_extra = 8523" of the "book" "id_book = 8522" of that particular user?, I currently use mongoosejs but I didn't succeed, I tried many stuffs, but whatever I tried was working just till the first level of nested doc.
{
"_id":{
"$oid":"5e32fce08919b53ad66cf694"
},
"user_id":{
"$numberInt":"258787"
},
"username":"daaaa",
"firstname":"davide",
"api_key":"7b031c21edf1237c554867622ad1154f",
"books":[
{
"_id":{
"$oid":"5e356323a0ef6319ebb60162"
},
"id_book":{
"$numberInt":"8522"
},
"blob_annotation":null,
"extra_id":{
"$numberInt":"995176"
},
"extras":[
{
"_id":{
"$oid":"5e356324a0ef6319ebb60163"
},
"id_extra":{
"$numberInt":"8523"
},
"type":"gallery_audio",
"label":"Inverno a Boscodirovo"
},
{
"_id":{
"$oid":"5e356324a0ef6319ebb60164"
},
"id_extra":{
"$numberInt":"8524"
},
"type":"gallery_audio",
"label":"Storia di Primavera"
}
],
"raccolte":[
]
}
],
}

Try using elemMatch in conjunction with $:
db.books.update(
{
books: {
$elemMatch: {
"id_book": 8522,
"extras.id_extra": 8523
}
},
user_id: 258787
},
{
$pull: {
"books.$.extras": {
"id_extra": 8523
}
}
}
)

You may do this trick: Filter "extras" with "id_extra = 8523" of the "book" "id_book = 8522" and save documents again in MongoDB
db.collection.aggregate([
{
$match: {
"books.id_book": 8522
}
},
{
$addFields: {
"books": {
$reduce: {
input: "$books",
initialValue: [],
in: {
$concatArrays: [
"$$value",
[
{
_id: "$$this._id",
id_book: "$$this.id_book",
blob_annotation: "$$this.blob_annotation",
extra_id: "$$this.extra_id",
raccolte: "$$this.raccolte",
extras: {
$filter: {
input: "$$this.extras",
cond: {
$ne: [
"$$this.id_extra",
8523
]
}
}
}
}
]
]
}
}
}
}
}
])
MongoPlayground

Related

how to catch mongo change streams when one key in object gets updated

I am using the mongo change stream to update some of my data in the cache. This is the Documentation i am following.
I want to know when one of the keys in my object gets updated.
Schema :- attributes: { position: { type: Number } },
How will I come to know when the position will get updated?
This is how my updateDescription object looks like after updation
updateDescription = {
updatedFields: { 'attributes.position': 1, randomKey: '1234'},
removedFields: []
}
Tried this and its not working
Collection.watch(
[
{
$match: {
$and: [
{ operationType: { $in: ['update'] } },
{
$or: [
{ 'updateDescription.updatedFields[attributes.position]': { $exists: true } },
],
},
],
},
},
],
{ fullDocument: 'updateLookup' },
);
I was able to fix it like this,
const streamUpdates = <CollectionName>.watch(
[
{
$project:
{
'updateDescription.updatedFields': { $objectToArray: '$updateDescription.updatedFields' },
fullDocument: 1,
operationType: 1,
},
},
{
$match: {
$and: [
{ operationType: 'update' },
{
'updateDescription.updatedFields.k': {
$in: [
'attributes.position',
],
},
},
],
},
},
],
{ fullDocument: 'updateLookup' },
);
and then do something with the stream
streamUpdates.on('change', async (next) => {
//your logic
});
Read more here MongoDB

Javascript mongodb aggregation filter not working

It's my line of code you see below is not working! It always returns an empty array value.
Please help me!
That's working!
const data = await NumbersModel.aggregate([
{
$project: {
Datas: {
$filter: {
input: "$Datas",
as: "data",
cond: { $gte: [ "$$data.time", lastdata ] }
}
}
}
])
That's not working!
const data = await NumbersModel.aggregate([
{
$project: {
Datas: {
$filter: {
input: "$Datas",
as: "data",
cond: {
$and: [
{ $gte: [ "$$data.time", lastdata ], },
{ $eq: [ "$$data.number", req.query.number ] }
]
}
}
}
}
}
])
It's working :)
const data = await NumbersModel.find({ "Datas.time": { $gte: lastdata }, Number: req.query.number })

Filter array and document in MongoDB

Schema
[
{
_id:"doc1",
type:"SR",
title:"...",
description:"...",
author:"5",
posts:[
{
author:"1",
title:"..."
},
{
author:"2",
title:"..."
},
{
author:"1",
title:"..."
}
]
},
{
_id:"doc2",
type:"SA",
title:"...",
description:"...",
posts:[],
author:"5"
}
]
Every Document will have type either SA or SR. If type is SA then posts will be an empty array, otherwise it'll non empty.
Now, i want to get document and array elements based on certain conditions.
if type is SA and authorId=5 then return the entire document.
if type is SR then return the elements of posts where authorId=1
When type is SA then i would like to get title,description,.. of the document otherwise get the posts by filter.
My Query
Using mongoose
Blog.find({
$or: [
{
$and: [
{ type: "SA" },
{ authorId:"5" }
]
},
{
"posts.authorId": "1"
}
]
}, {
posts: {
$filter: {
input: "$posts",
as: "post",
cond: {
$eq: ["$$post.authorId", "1"]
}
}
}
})
.then(posts => {
console.log(posts)
})
.catch(err => {
console.log(err);
})
Returned document
[
{
_id:"doc1",
posts:[
{
author:"1",
title:"..."
},
{
author:"1",
title:"..."
}
]
},
{
_id:"doc2",
posts:[]
}
]
How can i include other attribute of doc2?

How to retrieve data from a complex data structure in MongoDB?

Data:
Is there any way to access all of these "lineText" fields from the collection in MongoDB through a single query?
Try this
db.collectionName.aggregate([
{ $unwind: "$text" },
{ $unwind: "$text.paragraphs" },
{
$group: {
_id: null,
result: {
$push: {
$arrayElemAt: ["$text.paragraphs.lineText", 0]
}
}
}
},
{
$project: {
result: {
$reduce: {
input: "$result",
initialValue: "",
in: { "$concat": ["$$value", "$$this"] }
}
}
}
}
]);

(mongoDB) find with empty or null values

how to make a mongodb collection find (db.collection.find) with empty values?
currently i have:
function test(s) {
if (!s) {
return null;
} else {
return s;
}
}
var content = {
date: {
from: '2017-10-15',
to: '2017-11-15'
},
'name': 'some text', //this can be null or empty
'text': 'some other text' //this can be null or empty
}
col.find({
"date": {
$gte: new Date(content.date.from),
$lte: new Date(content.date.to)
},
"name": {
$ne: {
$type: null
},
$eq: test(content.name)
},
"text": {
$ne: {
$type: null
},
$eq: test(content.text)
},
}).toArray((err, items) => {
console.log(items)
});
but it returns an empty array, because "name" or "text" is null / an empty string,
i want that it query only the values that have something specified or ignore it (like content.name is something in it or its empty)
how do i get it? i already searched ... but didnt found something
thanks!
( already testet mongoDB : multi value field search ignoring null fields)
Versions:
Node: 8.9.0
(npm) mongodb: 2.2.33
mongodb: 3.4
Try using $and, $or operators. Something like.
col.find({
$and:[
{"date": {$gte: new Date(content.date.from),$lte: new Date(content.date.to)}},
{"$or":[{"name": {$ne: {$type: null}}},{"name":test(content.name)}]},
{"$or":[{"text": {$ne: {$type: null}}},{"text":test(content.text)}]}
]
}).toArray((err, items) => {
console.log(items)
});
col.find({
$and: [
{
$and: [
{
"date": {
$gte: new Date(content.date.from)
}
},
{
"date": {
$lte: new Date(content.date.to)
}
},
]
},
{
$or: [
{ 'name': null },
{ 'name': content.name }
]
},
{
$or: [
{ 'text': null },
{ 'text': content.text }
]
}
]
})
Edited:
col.find({
$and: [
{
$and: [
{
"date": {
$gte: new Date(content.date.from)
}
},
{
"date": {
$lte: new Date(content.date.to)
}
},
]
},
{
$or: [
{ 'name': null },
{ 'name':'' }
{ 'name': content.name }
]
},
{
$or: [
{ 'text': null },
{ 'text': '' },
{ 'text': content.text }
]
}
]
})
null and empty is different, you need to add one more condition for empty string in query.
Logical Query Operators

Categories

Resources