MongoDB find where resoult + value > when 100 - mongodb

I have the following db structure:
[
{
"_id": 1,
"family": "First Family",
"kids": [
{
"name": "David",
"age": 10
},
{
"name": "Moses",
"age": 15
}
]
},
{
"_id": 1,
"family": "Second Family",
"kids": [
{
"name": "Sara",
"age": 17
},
{
"name": "Miriam",
"age": 45
}
]
}
]
I want to select all families that have a kid that his age + 10 is bigger then 30.
What would be the best way to achieve this?

please find query below
db.collection.find({ "kids.age":{$gt:20}})

Related

How can I get only specific object from nested array mongodb

I'm using mongoDB with PHP. I know how to get the document based on product_id, but I need only a specific object from the whole document, I don't know how to get only specific object from nested array based on product_id.
for ex. My expected output is:
products": [
{
"product_id": 547,
"name": "cola",
"quantity": 24
}
]
then make some changes on object p.s update the quantity then update it to the database.
My collection looks like
"_id": {
"$oid": "62ed30855836b16fd38a00b9"
},
"name": "drink",
"products": [
{
"product_id": 547,
"name": "cola",
"quantity": 24
},
{
"product_id": 984,
"name": "fanta",
"quantity": 42
},
{
"product_id": 404,
"name": "sprite",
"quantity": 12
},
{
"product_id": 854,
"name": "water",
"quantity": 35
}
]
}
Try this:
db.getCollection('test').aggregate([
{
"$unwind": "$products"
},
{
"$match": {
"products.product_id": 547
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$$ROOT",
"$products"
]
}
}
},
{
"$project": {
"products": 0
}
}
])
The query gives the following output:
{
"name" : "cola",
"product_id" : 547,
"quantity" : 24
}

How to sort a field inside an array in MongoDB aggregation

mongo playground
I want to sort the views from biggest to smallest inside for each category. How to sort this?
So the expected outcome should be like this:
[
{
"_id": "101",
"cars": [
{
"carName": "CyberTruck",
"driverId": "202",
"views": 50
},
{
"carName": "Model 3",
"driverId": "202",
"views": 40
},
{
"carName": "Model x",
"driverId": "202",
"views": 30
}
],
"categoryName": "Tesla"
},
{
"_id": "102",
"cars": [
{
"carName": "X1",
"driverId": "201",
"views": 20
}
],
"categoryName": "BMW"
}
]

Sum items in a TSQL JSON column

Lets say I have a table and in a "data" NVARCHAR(MAX) column, I have this JSON:
[
{
"room": "kitchen",
"items": [
{
"name": "table",
"price": 100
}
]
},
{
"room": "bedroom",
"items": [
{
"name": "bed",
"price": 250
},
{
"name": "lamp",
"price": 50
}
]
},
{
"room": "bathroom",
"items": [
{
"name": "toilet",
"price": 101
},
{
"name": "shower",
"items": [
{
"name": "shower curtain",
"price": 10
},
{
"name": "shower head",
"price": 40
}
]
}
]
}
]
Using TSQL, can I somehow SUM all prices in the JSON? Please notice that my "price" is in different levels in the JSON file.
And furthermore, can I make a computed column that will SUM all the prices in the JSON column?
In JSon you would have to treat all nodes and check if another sublevel including "Price" exists. As text it is easier. This example is for one cell.
The idea above to insert the result to another column in the table is a good one.
You can implement a trigger after every INSERT / UPDATE to calculate instead of a computed column.
declare #str varchar(4000)='[ { "room": "kitchen", "items": [ { "name": "table", "price": 100 } ] }, { "room": "bedroom", "items": [ { "name": "bed", "price": 250 }, { "name": "lamp", "price": 50 } ] }, { "room": "bathroom", "items": [ { "name": "toilet", "price": 101 }, { "name": "shower", "items": [ { "name": "shower curtain", "price": 10 }, { "name": "shower head", "price": 40 } ] } ] } ]'
, #sub varchar(15);
drop table if exists #prices;
create table #prices(price int);
WHILE patindex('%"price": %',#str) > 0
begin
SELECT #sub=SUBSTRING(#str, patindex('%"price": %',#str), 15)
WHILE PatIndex('%[^0-9]%', #sub) > 0
SET #sub = Stuff(#sub, PatIndex('%[^0-9]%', #sub), 1, '');
insert into #prices select try_cast(#sub as int);
SET #str = Stuff(#str, patindex('%"price": %',#str), 15, '');
end;
select sum(price) from #prices;

MongoDB - Way to find closest results from arrays inside every document

I want to find closest result from array inside document for every doc, and project it new object using MongoDB. It will be easier to explain what I trying to do by example:
Doc schema:
{
"id": "string",
"name": "string",
"track" : [
{
"time": "number",
"distance": "number"
}
]
}
EXAMPLE:
I want to find closest results for every doc for time equals 4
Input data:
[
{
"id": "1",
"name": "test1",
"track" : [
{
"time": 0,
"distance": 0
},
{
"time": 1,
"distance": 5
},
{
"time": 3,
"distance": 17
},
{
"time": 4,
"distance": 23
},
{
"time": 6,
"distance": 33
}
]
},
{
"id": "2",
"name": "test2",
"track" : [
{
"time": 0,
"distance": 0
},
{
"time": 1,
"distance": 5
},
{
"time": 2,
"distance": 12
},
{
"time": 4,
"distance": 26
},
{
"time": 6,
"distance": 32
}
]
},
{
"id": "3",
"name": "test3",
"track" : [
{
"time": 0,
"distance": 0
},
{
"time": 1,
"distance": 5
},
{
"time": 3,
"distance": 12
}
]
}
]
Output data:
[
{
"id": "1",
"result" : {
"time": 4,
"distance": 23
}
},
{
"id": "2",
"result" : {
"time": 4,
"distance": 26
}
},
{
"id": "3",
"result" : {
"time": 3,
"distance": 12
}
}
]
Is it possible to do this using MongoDB?
db.collection.aggregate([
{
"$addFields": {
"tracks": {
"$filter": {
"input": "$track",
"as": "track",
"cond": {
"$lte": [
"$$track.time",
4
]
}
}
}
}
},
{
"$addFields": {
"tracks": {
"$slice": [
"$tracks",
-1
]
}
}
},
{
"$unwind": "$tracks"
},
{
"$project": {
"tracks": 1,
"name": 1
}
}
])
Play
It does below things:
Finds whose track time is <=4 and adds it to an array called items
Then it gets the last element - i.e closer element
Take the element from array - unwind
Projects what is needed.

MongoDB nested array aggregation

I want to aggregate data for the following sample array.
[
{
"_id": "5b7c0540342100091a375793",
"pages": [
{
"name": "ABCD",
"sections": [
{
"name": "sectionThird",
"id": 2,
"value": [
10,
50,
20
]
}
]
}
]
},
{
"_id": "5b3cd546342100514b4683a2",
"pages": [
{
"name": "ABCD",
"sections": [
{
"name": "sectionFourth",
"id": 2,
"value": [
19,
5,
8
]
},
{
"name": "sectionThird",
"id": 2,
"value": [
60
]
}
]
},
{
"name": "EFGH",
"sections": [
{
"name": "sectionFourth",
"id": 2,
"value": [
5
]
},
{
"name": "sectionThsads",
"id": 2,
"value": [
8
]
}
]
}
]
}
]
I want the following output:
[
{
"page": "ABCD",
"sections": [
{
"name": "sectionThird",
"totalValue": 140
},
{
"name": "sectionFourth",
"totalValue": 32
}
]
},
{
"page": "EFGH",
"sections": [
{
"name": "sectionFourth",
"totalValue": 5
},
{
"name": "sectionThsads",
"totalValue": 8
}
]
}
]
In the above sample array, you can see there are multiple documents with "page" as one of the keys which are also an array of objects. Each page object has a key "name" which is going to be unique for each object in "page" array. The "page" object has "sections" key and they also have "name" key in them which is going to be unique for each object.
So the output array is grouped by page.name then in that its grouped by sections.name from all the page objects with the sum of all the value array throughout sections inside a page object with the same section name.
You can use below aggregation.
$unwind each page and section followed by $group with $sum to sum the values for each section and $push to push the sections values back into page array.
db.col.aggregate([
{"$unwind":"$pages"},
{"$unwind":"$pages.sections"},
{"$group":{
"_id":{"pagename":"$pages.name","sectionname":"$pages.sections.name"},
"totalTime":{"$sum":{"$sum":"$pages.sections.value"}}
}},
{"$group":{
"_id":"$_id.pagename",
"sections":{"$push":{"name":"$_id.sectionname","totalTime":"$totalTime"}}
}}])