I have this document with this structure
{
"itemA": {
"subItemA": {
"20200104": [
{
"item": 1,
"item2": 2,
"item3": 3
},
{
"item": 4,
"item2": 5,
"item3": 6
},
{
"item": 7,
"item2": 8,
"item3": 9
}
]
}
}
}
Let's say I know the key of itemA, subItemA, and 20200104 and i want to retrieve the data so it will look like this:
[
{
"item": 1,
"item2": 2,
"item3": 3
},
{
"item": 4,
"item2": 5,
"item3": 6
},
{
"item": 7,
"item2": 8,
"item3": 9
}
]
This may be possible if I use JavaScript function (like db.data.find().forEach(function () ....) but is it possible to only use the "native query"?
First $unwind the array then use $replaceRoot
db.collection.aggregate([
{
$unwind: "$itemA.subItemA.20200104"
},
{
$replaceRoot: {
newRoot: "$itemA.subItemA.20200104"
}
}
])
Related
I have a document similar like this in mongodb with collection name: "movie" :-
collection = movie
[{
"_id": {
"$oid": "573a1390f29313caabcd446f"
},
"imdb": {
"rating": 6.6,
"votes": 1375,
"id": 832
},
"review": {
"rating": 6.6,
"votes": 1375,
"id": 832
}
},
{
"_id": {
"$oid": "573a1390f29313caabcd45f7"
},
"imdb": {
"rating": 4.6,
"votes": 1375,
"id": 832
},
"review": {
"rating": 8,
"votes": 432,
"id": 322
}
}]
How can I make a pipeline to group and count the number of based on the
average of rating in review?
You can use $facet and $bucket for that:
db.movie.aggregate( [
{
$facet: {
"review_rating": [
{
$bucket: {
groupBy: "$review.rating",
boundaries: [0, 3, 5, 10], // Boundaries for the buckets
default: "Other", // In case some data do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 }
}
}
}
],
"imbd_rating": [
{
$bucket: {
groupBy: "$imdb.rating",
boundaries: [0, 3, 5, 10], // Boundaries for the buckets
default: "Other", // In case some data do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 }
}
}
}
]
}
}
])
That should count the number of elements of each bucket for both review.rating and imdb.rating.
If you need more information, visit $facet in MongoDB Docs.
I have a collection of this kind of document:
{
"_id": {
"$oid": "6047b855a6ce7d24a4cda693"
},
"address": "Bergamo, Via S. Bernardino, 57",
"products": [{
"productId": "6047b855a6ce7d24a4cda694",
"qty": 7,
"alarmTh": 5
}, {
"productId": "6047b855a6ce7d24a4cda695",
"qty": 5,
"alarmTh": 5
}],
"_class": "warehouseservice.team2.warehouseservice.models.Warehouse"
}
I need to find a product with a specific productId. Let's say that I want the object with Id = 6047b855a6ce7d24a4cda694, the result that I want is the following:
{
"productId": "6047b855a6ce7d24a4cda694",
"qty": 7,
"alarmTh": 5
}
I tried with this:
db.warehouse.find({"products.productId": "6047b855a6ce7d24a4cda694"}, {"products.$": 1, _id: 0})
but this returns:
{ products: [ { productId: '6047b855a6ce7d24a4cda694', qty: 7, alarmTh: 5 } ] }
so an array, but I want only one single object.
Thanks
You can use the aggregation pipeline and $replaceRoot:
db.collection.aggregate([
{
"$match": {
"products.productId": "6047b855a6ce7d24a4cda694"
}
},
{
"$project": {
products: {
"$first": "$products"
}
}
},
{
"$replaceRoot": {
"newRoot": "$products"
}
}
]);
Output:
[
{
"alarmTh": 5,
"productId": "6047b855a6ce7d24a4cda694",
"qty": 7
}
]
I want to find all elements matching product "bat". My structure for database is as follows
[
{
"key": 1,
"productArray" : [
{
"requirementId": 5,
"product": "bat"
},
{
"requirementId": 6,
"product": "Pen"
},
]
},
{
"key": 2
},
{
"key": 3,
"productArray": [
{
"requirementId": 1,
"product": "bat"
},
{
"requirementId": 2,
"product": "Pen"
},
{
"requirementId": 3,
"product": "bat"
},
{
"requirementId": 4,
"product": "bat"
}
]
}
]
I have tried the following query but this query is returning only one matching element.
db.collection.find({"key": 3}, {"productArray": {"$elemMatch": { "product": "bat"}}})
result of above query is as follows
[
{
"_id": ObjectId("5a934e000102030405000002"),
"productArray": [
{
"product": "bat",
"requirementId": 1
}
]
}
]
Can I get expected output for my problem is as follows using mongodb query Or should I use another approach for my case:
My expected output is as follows
[
{
"productArray": [
{
"requirementId": 1,
"product": "bat"
},
{
"requirementId": 3,
"product": "bat"
},
{
"requirementId": 4,
"product": "bat"
}
]
}
]
As you found, $elemMatch but also $ are lazy operators and return the first element that matches.
You could add a pipeline in find (mongoDB 4.4+) but aggregation is better supported:
db.collection.aggregate({
$match: {
key: 3
}
},
{
$project: {
productArray: {
"$filter": {
"input": "$productArray",
"as": "p",
"cond": {
$eq: [
"$$p.product",
"bat"
]
}
}
}
}
})
Live version
{
"userid": 1,
"following": [2, 3],
"salary": 1000,
"age": 19
},
{
"userid": 2,
"following": [],
"salary": 2000,
"age": 25
},
{
"userid": 3,
"following": [2],
"salary": 1500,
"age": 20
},
"following" shows the userid of the people the user follows.
I would like to have an output query showing the userid and the salary of those that he follows only (no need age and the user's salary). I saw that $lookup() could be used but I am unsure of using it.
My desired output is shown below, may I know if it is possible? I am also open to any other outputs. Thank you in advance!
{
"userid": 1,
"following": [{2, 2000}, {3, 1500}]
},
{
"userid": 2,
"following": []
},
{
"userid": 3,
"following": [{2, 2000}]
}
You can use graphLookup to join the collection to itself, then use project stage to exclude unwanted fields like this:
db.collection.aggregate([
{
$graphLookup: {
from: "collection",
startWith: "$following",
connectFromField: "following",
connectToField: "userid",
as: "following",
maxDepth: 0
}
},
{
$project: {
"_id": 0,
"userid": 1,
"following.salary": 1,
"following.userid": 1
}
}
])
The output is not the same as you wanted, but as you said you are open to all suggestions I posted:
[
{
"following": [
{
"salary": 2000,
"userid": 2
},
{
"salary": 1500,
"userid": 3
}
],
"userid": 1
},
{
"following": [],
"userid": 2
},
{
"following": [
{
"salary": 2000,
"userid": 2
}
],
"userid": 3
}
]
Playground:
https://mongoplayground.net/p/WnF1vRY5Avr
Well, i have a complicated issue. at least it is complicated for myself.
So i have an Array which has an Array that has an Array in it.
and i want to filter The very top array based on properties inside the deepest array.
Lets say i have this Array of objects
var garages = [{
"GarageId": 1,
"GarageName": "Garage_001",
"Sections": [{
"SectionId": 1,
"Name": "Section_002",
"Cars": [{
"Id": 5,
"Model": "Bmw"
}, {
"Id": 6,
"Model": "Mercedes"
}]
}, {
"SectionId": 2,
"Name": "Section_003",
"Cars": [{
"Id": 8,
"Model": "Toyota"
}, {
"Id": 6,
"Model": "Mercedes"
}]
}]
},
{
"GarageId": 6,
"GarageName": "Garage_006",
"Sections": [{
"Id": 1,
"Name": "Section_007",
"Cars": [{
"Id": 5,
"Model": "Bmw"
}, {
"Id": 6,
"Model": "Mercedes"
}]
}, {
"Id": 2,
"Name": "Section_003",
"Cars": [{
"Id": 8,
"Model": "Toyota"
}, {
"Id": 6,
"Model": "Mercedes"
}]
}]
}
]
And i want to retrieve a list of garages that contain a Hyundai for example. how can i do it?
i have been trying for hours and this is what i came up with. it may be a stupid piece of code but i just got confused dealing with this much nested Arrays!
So my code is this:
garages: any[] = [];
selectedCarModel: number: 8;
filterOnCarModel(carId) {
this.garages = getGaragesFromServed();
this.selectedCarModel = this.CarModels.find(c => c.Id == id);
let filteredArray = this.garages
.filter((garage) =>
garage.Sections).
filter((section) =>
study.Cars.find((car) => car.Id == carId));
this.garages = filteredArray;
}
Thank you for understanding
var filteredGarages = garages.filter(garage =>
garage.Sections.filter(section =>
section.Cars.filter(car => car.Model.indexOf("Bmw")>=0)
.length > 0)
.length > 0)