Below is my mongodb structure
[
{
"_id": "com.android.angrybirds",
"rating": [
{
"user": "BBE74610BEE1A92784FDB",
"value": "1"
},
{
"user": "BBE74610BEE1A92784F",
"value": "5"
},
{
"user": "BBE74610BEE1A9784F",
"value": "5"
}
]
}
]
I want to group and count the unique ratings. I tried to use aggregate, group but it didn't work.
Expected output
[
{
"_id": "com.avatarrom.angrybirds",
"rating": [
{
"1": 1,
"5": 2
}
]
}
]
Like #RickyA said, your aggregation query would be interesting. What you need is the aggregate function in combination with the group operator. This post has a nice sample how you can do that.
Related
I try to query data from MongoDB using this line of code:
forms = await AllForm.find({
answers: {
$all: [{ $elemMatch: { dateCreate: "2022-10-25" } }],
},
It was supposed to return dates that are only "2022-10-25", but it turns out that it selected all the dates with the result below:
"status": true,
"message": "LIST_FORM",
"forms": [
{
"_id": "635711356b220b918529c29a",
"formId": "635711356b220b918529c298",
"title": "Quality",
"department": "Quality",
"answers": [
{
"username": "jansenstan24sdasa#gmail.com",
"dateCreate": "2022-10-25",
"Keterangan": "john#nabas.com",
"Jam_Kerja": "14:09"
},
{
"username": "jansenstan2410#gmail.com",
"dateCreate": "2022-10-24",
"Keterangan": "john#dose.com",
"Jam_Kerja": "10:50"
}
],
"createdAt": "2022-10-24T22:27:01.673Z",
"updatedAt": "2022-10-24T22:32:27.683Z",
"__v": 0
},
{
"_id": "63571d2285d6fb180cfa9f84",
"formId": "63571d2285d6fb180cfa9f82",
"title": "Quality_2",
"department": null,
"answers": [
{
"username": "jansenstan24#gmail.com",
"dateCreate": "2022-10-25",
"Test": "john#nabatisnack.com",
"Date": "2022-10-12T00:00:00.000Z"
},
{
"username": "jansenstan24#gmail.com",
"dateCreate": "2022-10-25",
"Test": "john#nabatisnack.com",
"Date": "2022-10-12T00:00:00.000Z"
}
],
"createdAt": "2022-10-24T23:17:54.995Z",
"updatedAt": "2022-10-24T23:19:29.981Z",
"__v": 0
}
]
Can someone please tell me where did I do wrong with the query?
Think that the .find() query unable to complete such a complex projection.
You may look for aggregation query.
$match - With dot notation, find the document(s with forms array contain the document with dateCreate is "2022-10-25" in nested answers array.
$set - Set the answers array.
2.1. $filter - Filter the matched document in the answers array.
forms = await AllForm.aggregate([
{
$match: {
"answers.dateCreate": "2022-10-25"
}
},
{
$set: {
answers: {
$filter: {
input: "$answers",
cond: {
$eq: [
"$$this.dateCreate",
"2022-10-25"
]
}
}
}
}
}
])
Demo # Mongo Playground
My collection has array "name" with objects inside. I need to remove only those objects inside array where "name.x" is blank.
"name": [
{
"name.x": [
{
"_id": "607e7fcca57aa56e2a06b57b",
"name": "abc",
"type": "123"
}
],
"_id": {
"$oid": "62232cd70ce38c5007de31e6"
},
"qty": "1.0",
"Unit": "pound,lbs"
},
{
"name.x": [
{
"_id": "607e7fcca57aa56e2a06b430",
"name": "xyz",
"type": "123"
}
],
"_id": {
"$oid": "62232cd70ce38c5007de31e7"
},
"qty": "1.0",
"Unit": "pound,lbs"
},{
"name.x": []
,
"_id": {
"$oid": "62232cd70ce38c5007de31e7"
},
"qty": "1.0",
"Unit": "pound,lbs"
}
I tried to get all the ids where name.x is blank using python and used $pull to remove objects base on those ids.But the complete array got deleted.How can I remove the objects that meet the condition.
Think MongoDB update with aggregation pipeline meets your requirement especially to deal with the field name with ..
$set - Update the name array field by $filter name.x field is not an empty array.
db.collection.update({},
[
{
$set: {
name: {
$filter: {
input: "$name",
cond: {
$ne: [
{
$getField: {
field: "name.x",
input: "$$this"
}
},
[]
]
}
}
}
}
}
],
{
multi: true
})
Sample Mongo Playground
I have the collection blow in mongodb:
{
"Id": "5",
"Group": [
{
"Name": "frank",
"Roll": "123"
}
]
},
{
"Id": "6",
"Group": [
{
"Name": "John",
"Roll": "124"
}
]
},
{
"Id": "7",
"Group": [
{
"Name": "John",
"Roll": "125"
}
]
}
The name "John" appears twice. I would like to display the number of each name that appears more than once:
{"Name": "John", "Count":2 }
You can use this aggregation query:
First $unwind to deconstruct the array and get all values as an object.
Then group by the name and $sum 1 for each name.
And then $match to get those values which exists more than one time (i.e. are repeated)
And last stage is to output values you want, in this case Name and Count.
db.collection.aggregate([
{
"$unwind": "$Group"
},
{
"$group": {
"_id": "$Group.Name",
"Count": {
"$sum": 1
},
}
},
{
"$match": {
"Count": {
"$gt": 1
}
}
},
{
"$project": {
"_id": 0,
"Name": "$_id",
"Count": 1
}
}
])
Example here
I have the following collection:
{
"invoice": {
"data": [{
"name": "VOUCHERNUMBER",
"value": "59302311"
}, {
"name": "VOUCHERDATE",
"value": "2020-02-20"
}
]
}
},
{
"invoice": {
"data": [{
"name": "VOUCHERNUMBER",
"value": "59112389"
}, {
"name": "VOUCHERDATE",
"value": "2020-02-20"
}
]
}
},
{
"invoice": {
"data": [{
"name": "VOUCHERNUMBER",
"value": "59302378"
}, {
"name": "VOUCHERDATE",
"value": "2020-02-11"
}
]
}
}
My task is to build a query that find all invoices which invoicenumbers includes "11" (or any other substring).
So I built the following statement:
{"invoice.data.name": "VOUCHERNUMBER", "invoice.data.value": {$regex : "11"} }
I'm expecting a result of the first two objects, but because of the second value in the third object, mongodb returns me all three objects. Then I tried
{$and : [{"invoice.data.name": "VOUCHERNUMBER"}, {"invoice.data.value": {$regex : "11"}}]}
with the same result ...
So I'm running out of ideas. Is there a solution to search for the string only in the value field where the corresponding "name" field contains "VOUCHERNUMBER"?
You need $elemMatch.
The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.
db.collection.find({
"invoice.data": {
"$elemMatch": {
"name": "VOUCHERNUMBER",
"value": {
$regex: "11"
}
}
}
})
Sample Mongo Playground
Being not familiar with Mongo and still progressing I came accross a problem I can't think to fix (and I don't know if it's feasible)
I have an Event document whose structure looks like this:
{
"_id": "6138451fb3a7d9564a0229fd"
"title": "Event 1",
"cohortsGroups": [
[
{
"_id": "6124beef59d728c82088fd59",
"name": "2022",
"type": "promotion"
},
{
"_id": "6124bf2159d728c82088fd60",
"name": "Toronto",
"type": "city"
}
],
[
{
"_id": "6124beef59d728c82088fd57",
"name": "2024",
"type": "promotion"
},
{
"_id": "6124bf2159d728c82088fd68",
"name": "Tokyo",
"type": "city"
}
],
]
},
{
"_id": "6138451fb3a7d9564a0229fe"
"title": "Event 2",
"cohortsGroups": [
[
{
"_id": "6124beef59d728c82088fd59",
"name": "2022",
"type": "promotion"
}
]
]
},
{
"_id": "6138451fb3a7d9564a0229fh"
"title": "Event 3",
"cohortsGroups": [
[
{
"_id": "6124beef59d728c82088fd21",
"name": "2022",
"type": "promotion"
},
{
"_id": "6124beef59d728c82088fd43",
"name": "Amsterdam",
"type": "city"
}
]
]
}
As you can see the field cohortsGroups is a double array of Objects. I would like to retrieve those events based on my user's object who possess also an array (simple) of cohorts
So for example let's say my user looks like this:
{
"firstName": "John",
"lastName": "Doe",
"cohortsRef": [
{
"_id": "6124beef59d728c82088fd59",
"name": "2022",
"type": "promotion"
},
{
"_id": "6124bf2159d728c82088fd60",
"name": "Toronto",
"type": "city"
}
]
}
To make it simple I would like to retrieve an event only if one of the set of cohorts in in his cohortsGroups have his cohorts all presents in the user object.
Taking that in mind and the above example I would only be able to retrive Event 1 and Event 2.
I can't retrieve Event 3 because even tho I have the Cohort 2022 in my user, it's paired with the Cohort Amsterdam which is not present in my user's cohorts, (eq: none of the cohort subarrays sets have their values entirely present in my user's cohorts).
I really hope someone can give me a hand on that problem, so far I've tried to map all the user's cohorts ID in an array and query by $elemMatch
Events.find({ cohortsGroups: { $elemMatch: { $elemMatch: { _id: { $in: [ '6124beef59d728c82088fd59', '6124bf2159d728c82088fd60' ] } } } } })
But this solution just retrieves every event that have a subarray cohort matching, it doesn't take into account the sets, so in this case it would also retrieve Event 3 - because 2022 is present - but it's paired with the cohort Amsterdam which is wrong.
Let me know if I wasn't clear enough, any help would be appreciated. At least to know if it's something doable as a mongo query.
Thanks a lot for reading !
This should work:
db.events.find({ cohortsGroups: { $elemMatch: { $not: {$elemMatch: { _id: { $nin: [ '6124beef59d728c82088fd59', '6124bf2159d728c82088fd60' ] } } } } } })
The outer $elemMatch, matches any document where any array in cohortsGroups matches the inner condition.
The inner condition
{ $not: {$elemMatch: { _id: { $nin: [ '6124beef59d728c82088fd59', '6124bf2159d728c82088fd60' ] } } } } }
is using a double negative with $not and $nin to find subarrays that have no element with an _id except those that you are searching for.