Query Documents In Array - mongodb

I have one embedded MongoDB document and I need to remove {nameofcontent:"miljox"} from the below-mentioned document.
{
_id: 1,
results: [
{ item: "A", score: 5, answers: [ { q:[{nameofcontent:"miljox"}]: 1, a: 4 }, { q:[{nameofcontent:"miljo"}], a: 6 } ] },
{ item: "B", score: 8, answers: [ { q:[{nameofcontent:"y"}], a: 8 }, { q: [{nameofcontent:"anil"}], a: 9 } ] }
]
}

Related

Condition in aggregation mongodb

I'm new in Mongodb and I try to learn aggregation.
My database look like this:
{
_id : 1,
a: 5,
b: 6,
c : {
ca: 3
cb: 5
}
},
{
_id : 1,
a: 3,
b: 4,
c : {
ca: 3
cb: 7
}
}
Is there anyway to :
- First: find max in c
- Second: create a new object like this:
{
a : [ 5, 3],
b : [6, 4],
c : [5, 7]
}
My apologies if this is a repeated question but I wasn't able to find a similar one.
Try this,
db.collection.aggregate([
{
$addFields: {
c: {
$objectToArray: "$c"
}
}
},
{
$group: {
_id: null,
a: {
$push: "$a"
},
b: {
$push: "$b"
},
c: {
$push: {
$max: "$c.v"
}
}
}
}
])
Mongo Playground

How to get several combinations of documents where sums of properties reach a certain value in Mongodb?

If we imagine this kind of document structure :
[
{
id: 1,
name: "",
values : {
a: 24,
b: 42
}
},
{
id: 2,
name: "",
values : {
a: 43,
b: 53
}
},
{
id: 3,
name: "",
values : {
a: 33,
b: 25
}
},
{
id: 4,
name: "",
values : {
a: 89,
b: 2
}
}
// ...
]
Is it possible to get one or more lists of documents where, for example, the sum of the $.values.a equals 100 and the sum of the $.values.b equals 120? Or if not is it possible to sort the bests fits with a kind of threshold?
For example, the best output can be something like that :
[
{
id: 1,
name: "",
values : {
a: 24,
b: 42
}
},
{
id: 2,
name: "",
values : {
a: 43,
b: 53
}
},
{
id: 3,
name: "",
values : {
a: 33,
b: 25
}
}
]
There is no any native implementation...
But, You can have desired results if your data meets some requirements:
You collection has no too much data (this solution scales badly)
Your id field is unique
Your collection has index for id field
Explanation
We sort by id
With $lookup with the same collection (it's important ´id´ to be indexed) and pick next 10 documents for the current document L i=(Doc i+1 ... Doc i+11)
With $reduce, we count from i ... i+n untill a > 100 and b > 120
With $facet, we separate lists which meets exactly a=100, b=120 results (equals) and threshold (+- 10 for values.a and values.b)
Last steps, if any equals exists, we ignore threshold. Otherwise, we take threshold.
db.collection.aggregate([
{
$sort: {
id: 1
}
},
{
$lookup: {
from: "collection",
let: {
id: "$id"
},
pipeline: [
{
$sort: {
id: 1
}
},
{
$match: {
$expr: {
$gt: [
"$id",
"$$id"
]
}
}
},
{
$limit: 10
}
],
as: "bucket"
}
},
{
$replaceRoot: {
newRoot: {
$reduce: {
input: "$bucket",
initialValue: {
a: "$values.a",
b: "$values.b",
data: [
{
_id: "$_id",
id: "$id",
name: "$name",
values: "$values"
}
]
},
in: {
a: {
$add: [
"$$value.a",
{
$cond: [
{
$and: [
{
$lt: [
"$$value.a",
100
]
},
{
$lt: [
"$$value.b",
120
]
}
]
},
"$$this.values.a",
0
]
}
]
},
b: {
$add: [
"$$value.b",
{
$cond: [
{
$and: [
{
$lt: [
"$$value.a",
100
]
},
{
$lt: [
"$$value.b",
120
]
}
]
},
"$$this.values.b",
0
]
}
]
},
data: {
$concatArrays: [
"$$value.data",
{
$cond: [
{
$and: [
{
$lt: [
"$$value.a",
100
]
},
{
$lt: [
"$$value.b",
120
]
}
]
},
[
"$$this"
],
[]
]
}
]
}
}
}
}
}
},
{
$facet: {
equals: [
{
$match: {
a: 100,
b: 120
}
}
],
threshold: [
{
$match: {
a: {
$gte: 90,
$lt: 110
},
b: {
$gte: 110,
$lt: 130
}
}
}
]
}
},
{
$project: {
result: {
$cond: [
{
$gt: [
{
$size: "$equals"
},
0
]
},
"$equals",
"$threshold"
]
}
}
},
{
$unwind: "$result"
}
])
MongoPlayground

Atomically move object by ID from one array to another in same document [duplicate]

This question already has an answer here:
Move an element from one array to another within same document MongoDB
(1 answer)
Closed 3 years ago.
I have data that looks like this:
{
"_id": ObjectId("4d525ab2924f0000000022ad"),
"arrayField": [
{ id: 1, other: 23 },
{ id: 2, other: 21 },
{ id: 0, other: 235 },
{ id: 3, other: 765 }
],
"someOtherArrayField": []
}
Given a nested object's ID (0), I'd like to $pull the element from one array (arrayField) and $push it to another array (someOtherArrayField) within the same document. The result should look like this:
{
"_id": ObjectId("id"),
"arrayField": [
{ id: 1, other: 23 },
{ id: 2, other: 21 },
{ id: 3, other: 765 }
],
"someOtherArrayField": [
{ id: 0, other: 235 }
]
}
I realize that I can accomplish this with a find followed by an update, i.e.
db.foo.findOne({"_id": param._id})
.then((doc)=>{
db.foo.update(
{
"_id": param._id
},
{
"$pull": {"arrayField": {id: 0}},
"$push": {"someOtherArrayField": {doc.array[2]} }
}
)
})
But I'm looking for an atomic operation like, in pseudocode, this:
db.foo.update({"_id": param._id}, {"$move": [{"arrayField": {id: 0}}, {"someOtherArrayField": 1}]}
Is there an atomic way to do this, perhaps using MongoDB 4.2's ability to specify a pipeline to an update command? How would that look?
I found this post that generously provided the data I used, but the provided solution isn't an atomic operation. Has an atomic solution become possible with MongoDB 4.2?
Here's an example:
> db.baz.find()
> db.baz.insert({
... "_id": ObjectId("4d525ab2924f0000000022ad"),
... "arrayField": [
... { id: 1, other: 23 },
... { id: 2, other: 21 },
... { id: 0, other: 235 },
... { id: 3, other: 765 }
... ],
... "someOtherArrayField": []
... })
WriteResult({ "nInserted" : 1 })
function extractIdZero(arrayFieldName) {
return {$arrayElemAt: [
{$filter: {input: arrayFieldName, cond: {$eq: ["$$this.id", 0]}}},
0
]};
}
extractIdZero("$arrayField")
{
"$arrayElemAt" : [
{
"$filter" : {
"input" : "$arrayField",
"cond" : {
"$eq" : [
"$$this.id",
0
]
}
}
},
0
]
}
db.baz.updateOne(
{_id: ObjectId("4d525ab2924f0000000022ad")},
[{$set: {
arrayField: {$filter: {
input: "$arrayField",
cond: {$ne: ["$$this.id", 0]}
}},
someOtherArrayField: {$concatArrays: [
"$someOtherArrayField",
[extractIdZero("$arrayField")]
]}
}}
])
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.baz.findOne()
{
"_id" : ObjectId("4d525ab2924f0000000022ad"),
"arrayField" : [
{
"id" : 1,
"other" : 23
},
{
"id" : 2,
"other" : 21
},
{
"id" : 3,
"other" : 765
}
],
"someOtherArrayField" : [
{
"id" : 0,
"other" : 235
}
]
}

How to use elemMatch to match nested array

I have some data structure like this
{
a: 1,
array1: [
{
b: 2
array2: [
{
// this is my target
c: 3,
d: 3
},
{
c: 4,
d: 4
}
]
},
{
b: 3
array2: [
{
c: 5,
d: 5
},
{
c: 6,
d: 6
}
]
}
]
}
I know use {"array1" : {"$elemMatch" : {"b" : 2} } } to match element of first level array1. But I don't know how to match element {c: 3, d: 3} of array2 of array1.
$elemMatch is used to state association among multiple fields within the same nested structure.
For eg. If you are looking to query c and d and need them to belong to the same sub-document, the you can query it like.
{"array1.array2" : {"$elemMatch" : {"c" : 3, "d":3} } }
Note: if you are querying on a single field, you dont really need to use $elemMatch (since there is no association)
For instance, in your query example, you can instead do
{"array1.b" : 2}
try this,it help me a lot.
{
"array1": {
"$elemMatch": {
"array2": {
"$elemMatch": {
"c": 3
}
}
}
}
}
let feed = await Doc.findOneAndUpdate(
{
$and: [
{
_id: req.params.id,
},
{
'feeds.$[].locations': {
$elemMatch: {
uniqueName,
},
},
},
],
},
{
$pull: {
//#ts-ignore
'feeds.$[].locations': { uniqueName },
},
},
{ new: true }
);

Mongo sorted list complexity

For the following sorted list:
{
sorted_list : [{name : <string>,score : <Number>}]
}
What are the complexities of the following commands (in 'O' notations)?
Find:
collection.find( { _id: 1}, { sorted_list: { $slice: [ <skip>, <limit> ] } } )
Insert:
collection.update(
{ _id: 1 },
{
$push: {
sorted_list: {
$each: [ { name: 3, score: 8 }, { name: 4, score: 7 }, { name: 5, score: 6 } ],
$sort: { score: 1 }
}
}
}
)
Remove:
collection.update({"sorted_list.name": name},{ $pull: { "sorted_list.name": <name> } },{ multi: true });
EDIT
Let's assume ther following index exists:
{ "sorted_list.name" : 1}