How to combine multiple aggregate query in a mongodb - mongodb
I want to find an easy way to combine 3 ratings together for a mongoDB query. Specifically, is there some way to combine 3 aggregate calls in one. So for example i have the below data. Which lists ratings for movies, either in imbd.rating, tomato.rating or metacritic, I'd like to find the top 2 movies for each of these ratings. The bottom query is how i'm fetching the top 2 results based on the tomato.rating
data
{
"title": "Once Upon a Time in the West",
"year": 1968,
"rated": "PG-13",
"runtime": 175,
"countries": [
"Italy",
"USA",
"Spain"
],
"genres": [
"Western"
],
"director": "Sergio Leone",
"writers": [
"Sergio Donati",
"Sergio Leone",
"Dario Argento",
"Bernardo Bertolucci",
"Sergio Leone"
],
"actors": [
"Claudia Cardinale",
"Henry Fonda",
"Jason Robards",
"Charles Bronson"
],
"plot": "Epic story of a mysterious stranger with a harmonica who joins forces with a notorious desperado to protect a beautiful widow from a ruthless assassin working for the railroad.",
"poster": "http://ia.media-imdb.com/images/M/MV5BMTEyODQzNDkzNjVeQTJeQWpwZ15BbWU4MDgyODk1NDEx._V1_SX300.jpg",
"imdb": {
"id": "tt0064116",
"rating": 8.6,
"votes": 201283
},
"tomato": {
"meter": 98,
"image": "certified",
"rating": 9,
"reviews": 54,
"fresh": 53,
"consensus": "A landmark Sergio Leone spaghetti western masterpiece featuring a classic Morricone score.",
"userMeter": 95,
"userRating": 4.3,
"userReviews": 64006
},
"metacritic": 80,
"awards": {
"wins": 4,
"nominations": 5,
"text": "4 wins \u0026 5 nominations."
},
"type": "movie"
},
{
"title": "A Million Ways to Die in the West",
"year": 2014,
"rated": "R",
"runtime": 116,
"countries": [
"USA"
],
"genres": [
"Comedy",
"Western"
],
"director": "Seth MacFarlane",
"writers": [
"Seth MacFarlane",
"Alec Sulkin",
"Wellesley Wild"
],
"actors": [
"Seth MacFarlane",
"Charlize Theron",
"Amanda Seyfried",
"Liam Neeson"
],
"plot": "As a cowardly farmer begins to fall for the mysterious new woman in town, he must put his new-found courage to the test when her husband, a notorious gun-slinger, announces his arrival.",
"poster": "http://ia.media-imdb.com/images/M/MV5BMTQ0NDcyNjg0MV5BMl5BanBnXkFtZTgwMzk4NTA4MTE#._V1_SX300.jpg",
"imdb": {
"id": "tt2557490",
"rating": 6.1,
"votes": 126592
},
"tomato": {
"meter": 33,
"image": "rotten",
"rating": 4.9,
"reviews": 188,
"fresh": 62,
"consensus": "While it offers a few laughs and boasts a talented cast, Seth MacFarlane's overlong, aimless A Million Ways to Die in the West is a disappointingly scattershot affair.",
"userMeter": 40,
"userRating": 3,
"userReviews": 62945
},
"metacritic": 44,
"awards": {
"wins": 0,
"nominations": 6,
"text": "6 nominations."
},
"type": "movie"
},
{
"title": "Wild Wild West",
"year": 1999,
"rated": "PG-13",
"runtime": 106,
"countries": [
"USA"
],
"genres": [
"Action",
"Western",
"Comedy"
],
"director": "Barry Sonnenfeld",
"writers": [
"Jim Thomas",
"John Thomas",
"S.S. Wilson",
"Brent Maddock",
"Jeffrey Price",
"Peter S. Seaman"
],
"actors": [
"Will Smith",
"Kevin Kline",
"Kenneth Branagh",
"Salma Hayek"
],
"plot": "The two best hired guns in the West must save President Grant from the clutches of a nineteenth-century inventor-villain.",
"poster": "http://ia.media-imdb.com/images/M/MV5BNDI5NDk5MjgxMl5BMl5BanBnXkFtZTcwNjI1MTUyMQ##._V1_SX300.jpg",
"imdb": {
"id": "tt0120891",
"rating": 4.8,
"votes": 124558
},
"tomato": {
"meter": 17,
"image": "rotten",
"rating": 4.1,
"reviews": 130,
"fresh": 22,
"consensus": "Bombastic, manic, and largely laugh-free, Wild Wild West is a bizarre misfire in which greater care was lavished upon the special effects than on the script.",
"userMeter": 28,
"userRating": 2.7,
"userReviews": 463740
},
"metacritic": 38,
"awards": {
"wins": 10,
"nominations": 11,
"text": "10 wins \u0026 11 nominations."
},
"type": "movie"
},
{
"title": "West Side Story",
"year": 1961,
"rated": "UNRATED",
"runtime": 152,
"countries": [
"USA"
],
"genres": [
"Crime",
"Drama",
"Musical"
],
"director": "Jerome Robbins, Robert Wise",
"writers": [
"Ernest Lehman",
"Arthur Laurents",
"Jerome Robbins"
],
"actors": [
"Natalie Wood",
"Richard Beymer",
"Russ Tamblyn",
"Rita Moreno"
],
"plot": "Two youngsters from rival New York City gangs fall in love, but tensions between their respective friends build toward tragedy.",
"poster": "http://ia.media-imdb.com/images/M/MV5BMTM0NDAxOTI5MF5BMl5BanBnXkFtZTcwNjI4Mjg3NA##._V1_SX300.jpg",
"imdb": {
"id": "tt0055614",
"rating": 7.6,
"votes": 67824
},
"awards": {
"wins": 18,
"nominations": 11,
"text": "Won 10 Oscars. Another 18 wins \u0026 11 nominations."
},
"type": "movie"
},
{
"title": "Slow West",
"year": 2015,
"rated": "R",
"runtime": 84,
"countries": [
"UK",
"New Zealand"
],
"genres": [
"Action",
"Thriller",
"Western"
],
"director": "John Maclean",
"writers": [
"John Maclean"
],
"actors": [
"Kodi Smit-McPhee",
"Michael Fassbender",
"Ben Mendelsohn",
"Aorere Paki"
],
"plot": "A young Scottish man travels across America in pursuit of the woman he loves, attracting the attention of an outlaw who is willing to serve as a guide.",
"poster": "http://ia.media-imdb.com/images/M/MV5BNTYxNDA5ODk5NF5BMl5BanBnXkFtZTgwNzMwMzIwNTE#._V1_SX300.jpg",
"imdb": {
"id": "tt3205376",
"rating": 7,
"votes": 19101
},
"tomato": {
"meter": 92,
"image": "certified",
"rating": 7.5,
"reviews": 115,
"fresh": 106,
"consensus": "Slow West serves as an impressive calling card for first-time writer-director John M. Maclean -- and offers an inventive treat for fans of the Western.",
"userMeter": 75,
"userRating": 3.7,
"userReviews": 9850
},
"metacritic": 72,
"awards": {
"wins": 2,
"nominations": 9,
"text": "2 wins \u0026 9 nominations."
},
"type": "movie"
},
{
"title": "An American Tail: Fievel Goes West",
"year": 1991,
"rated": "G",
"runtime": 75,
"countries": [
"USA"
],
"genres": [
"Animation",
"Adventure",
"Family"
],
"director": "Phil Nibbelink, Simon Wells",
"writers": [
"Flint Dille",
"Charles Swenson",
"David Kirschner"
],
"actors": [
"Phillip Glasser",
"James Stewart",
"Erica Yohn",
"Cathy Cavadini"
],
"plot": "A family of Emigre mice decide to move out to the west, unaware that they are falling into a trap perpetrated by a smooth talking cat.",
"poster": "http://ia.media-imdb.com/images/M/MV5BMTYzODMxNTUyNF5BMl5BanBnXkFtZTcwMTAwMzQyMQ##._V1_SX300.jpg",
"imdb": {
"id": "tt0101329",
"rating": 6.4,
"votes": 16013
},
"awards": {
"wins": 0,
"nominations": 0,
"text": ""
},
"type": "movie"
},
tomato.rating get
db.MovieData.aggregate([
{ "$unwind": "$tomato" },
{ "$sort": { "tomato.meter": -1 } },
{ "$limit": 2 },
{"$project": {title:1, "tomato.meter":1}},
])
imbd
db.MovieData.aggregate([
{ "$sort": { "imdb.rating": -1 } },
{ "$limit": 2 },
{"$project": {title:1, "imdb.rating":1}},
])
Meta critic
db.MovieData.aggregate([
{ "$sort": { "metacritic": -1 } },
{ "$limit": 2 },
{"$project": {title:1, "metacritic":1}},
])
These sort of "limitted" operations are perfectly suited to $facet:
db.MovieData.aggregate([
{ "$facet": {
"tomato": [
{ "$sort": { "tomato.meter": -1 } },
{ "$limit": 2 },
{"$project": {title:1, "tomato.meter":1}},
],
"imdb": [
{ "$sort": { "imdb.rating": -1 } },
{ "$limit": 2 },
{"$project": {title:1, "imdb.rating":1}},
],
"metacrtic": [
{ "$sort": { "metacritic": -1 } },
{ "$limit": 2 },
{"$project": {title:1, "metacritic":1}},
]
}}
])
Returns from the data in the question:
{
"tomato" : [
{
"_id" : ObjectId("5c80979542dd84d91e5547d9"),
"title" : "Once Upon a Time in the West",
"tomato" : {
"meter" : 98
}
},
{
"_id" : ObjectId("5c80979542dd84d91e5547dd"),
"title" : "Slow West",
"tomato" : {
"meter" : 92
}
}
],
"imdb" : [
{
"_id" : ObjectId("5c80979542dd84d91e5547d9"),
"title" : "Once Upon a Time in the West",
"imdb" : {
"rating" : 8.6
}
},
{
"_id" : ObjectId("5c80979542dd84d91e5547dc"),
"title" : "West Side Story",
"imdb" : {
"rating" : 7.6
}
}
],
"metacrtic" : [
{
"_id" : ObjectId("5c80979542dd84d91e5547d9"),
"title" : "Once Upon a Time in the West",
"metacritic" : 80
},
{
"_id" : ObjectId("5c80979542dd84d91e5547dd"),
"title" : "Slow West",
"metacritic" : 72
}
]
}
As long as the results are "small" then it's perfectly okay to run multiple pipelines this way.
If results are large it would be better to run independent queries and preferably in parallel ( i.e under Promise.all() for NodeJS for example ) and combine results ( as the Promise.all() example would ).
Whilst this effectively requires more database connections, that additional overhead is typically negated by the parallel processing. And of course means combined results ( especially when processed from cursors ) would not cause the BSON limit on a response to be broken.
NOTE: tomato is an Object and not an Array, so you don't use $unwind
Related
Elasticsearch date range query on date field with added buffer days
I have to get records (training) wherein I have a start_date, and I have to get all records that have not yet ended. So I don't have an end_date field, but just the start date, so end_date is start_date + 60 days. So what I need comprises all results that have "start_date" less than equal to "now" and "start_date + 60 days" greater than equal to "now" i.e. "now" is between start_date and "start_date + 60 days". So here's what I am trying. But I know "on_demand_start_date+60d" is incorrect. Can anyone help, how can this be done? "must": [ { "range": { "on_demand_start_date+60d": { "gte": "now" } } }, { "range": { "on_demand_start_date": { "lte": "now" } } } ] Below is a sample document: { "_index": "cdc_sse_content", "_type": "doc", "_id": "cdc_sse_publish_1140", "_score": null, "_source": { "country": "us", "event_source_time_zone": "", "source": "CVENT", "iSAPIRecord": true, "index_type": "content", "content_title": "***Test - API March 04 - 1", "event_technology": [ "Cloud & Computing", "Collaboration", "Services (CX)" ], "language_code": "en", "application_name": "event-selector", "event_type": "Hybrid event", "event_region": [ "North America" ], "event_time_zone": "UTC", "cdc_page_url": "https://www.google.com?EID=<95929>", "event_end_date": "2022-02-05T01:00", "event_filters": "", "created_by": "shaiwsha", "live_stream_end_date": null, "marketing_owner": "tparida", "event_on-demand_details": "", "search_filter_lables": [ "On-demand" ], "kafka": { "consumer_group": "sseadmin", "partition": 0, "offset": 181002, "topic": "SSEAdminContentPublished", "key": null }, "updated_by": "shaiwsha", "publish_date": "2022-02-15", "event_start_date": "2022-02-04T17:00", "status": "active", "eid": "95929", "es_index_fail": false, "cdc_id": "event-selector_1140", "event_image_url": "https://www.cisco.com/c/dam/assets/events/i/event-selector/2021/rsa_global_events_page_br_dark_600x400.png", "description": "Test 1 - This is a sample Hybrid event, that should the event type,Hybrid with City and country displayed. This is a sample In-Person that should disp", "selector_id": "cdc_event-selector_publish_1140", "event_livestream_url": "", "locale": "en_us", "event_registration_url": "https://sandbox-www.cvent.com/d/p7qgmk/4W?&EID=95929", "event_live_stream_details": "", "event_city": "Santa Clara", "event_registration_and_location_details": "", "#version": "1", "event_details": "", "start_date": "2022-02-07T19:37", "registration_start_date": "2022-02-18T09:00", "event_industry": [ "Manufacturing" ], "event_language": [ "Cantonese", "Dutch", "English" ], "event_state": "California", "live_stream_start_date": null, "on_demand_url": "https://www.google.com", "on_demand": [ "On-demand" ], "#timestamp": "2022-03-15T07:28:08.821Z", "registration_end_date": "2022-02-20T09:00", "recent_search_published_date": "2022-03-10T14:17:30.320Z", "event_country": "USA", "featured_event": [ "Featured event" ], "created_date": "2022-03-10T10:08:05.801Z", "last_update_ts": "2022/3/10 14:19:5", "updated_date": "2022-03-10T14:19:05.693Z" }, "sort": [ 1643994000000 ] }
mongodb update where argument exists
db.filmes.insertMany( [ { "num": 1, "title": "movie1", "category": "Horror", "review": 5, "cast": { "director": "R1", "artist": "A1" }, "exibition": [ "Lisboa", "Porto", "Braga" ] }, { "num": 2, "title": "movie2", "category": "Action", "review": 3, "cast": { "director": "R2", "artist": "A2" }, "exibition": [ "Lisboa", "Porto" ] }, { "num": 3, "title": "movie3", "category": "Animation", "review": 3, "cast": { "director": "R2", "artist": "A2" }, "exibition": [ "Lisboa", "Porto", "Viseu" ] }, { "num": 4, "title": "movie4", "category": "Animation", "review": 6, "cast": { "director": "R1", "artist": "A4" }, "exibition": [ "Lisboa", "Porto", "Braga" ] }, { "num": 5, "title": "movie5", "category": "Horror", "review": 5, "cast": { "director": "R3", "artist": "A3" }, "exibition": [ "Lisboa", "Porto" ] } ]); I need to update all the reviews to 10 where artist "A3" appears? I already tried : db.movies.updateMany({cast:{artist:"A3"}},{$set:{review:10}}) db.movies.update({artist:"A3"},{$ste:{review:10}}); and other that I cant remember, there's is a way to do it ?
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" } ]
In Mongo query in Subdocuments multiple fields
I have a collection in Mongo { "_id": 1, "favorites": { "artist": "Picasso", "food": "pizza" }, "finished": [ 17, 3 ], "badges": [ "blue", "black" ], "points": [ { "points": 85, "bo nus": 20 }, { "points": 85, "bonus": 10 } ] }{ "_id": 2, "favorites": { "artist": "Miro", "food": "meringue" }, "finished": [ 11, 25 ], "badges": [ "green" ], "points": [ { "points": 85, "bonus": 20 }, { "points": 64, "bonus": 12 } ] }{ "_id": 3, "favorites": { "artist": "Cassatt", "food": "cake" }, "finished": [ 6 ], "badges": [ "blue", "red" ], "points": [ { "points": 85, "bonus": 8 }, { "points": 55, "bonus": 20 } ] }{ "_id": 4, "favorites": { "artist": "Chagall", "food": "chocolate" }, "finished": [ 5, 11 ], "badges": [ "red", "black" ], "points": [ { "points": 53, "bonus": 15 }, { "points": 51, "bonus": 15 } ] }{ "_id": 5, "favorites": { "artist": "Noguchi", "food": "nougat" }, "finished": [ 14, 6 ], "badges": [ "orange" ], "points": [ { "points": 71, "bonus": 20 } ] }{ "_id": 6, "favorites": { "food": "pizza", "artist": "Picasso" }, "finished": [ 18, 12 ], "badges": [ "black", "blue" ], "points": [ { "points": 78, "b onus": 8 }, { "points": 57, "bonus": 7 } ] } I want to retrieve all elements having points = 85 and bonus = 20. Query will be db.temp2.find({"points":{"points":85,"bonus":20}}) it returns documents with id : 1 and 2. Now if i want to retrieve elements having ( points=85 and bonus = 20 ) and another sub-documents with {points=85 and bonus > 10). basically i want to retrieve element with id = 2 if query is db.temp2.find({$and:[{"points":{"points":85,"bonus":20}},{"points":{"points":64,"bonus":{$gte:10}}}]}).pretty() it gives no results whereas query db.temp2.find({$and:[{"points":{"$elemMatch":{"points":85,"bonus":20}}},{"points":{"$elemMatch":{"points":64,"bonus":{$gte:10}}}}]}) gives me id=2. Same thing i tried with anther sets [ { "name": "User1", "tags": [ { "k": "group", "v": "test" }, { "k": "color", "v": "blue" } ] }, { "name": "User2", "tags": [ { "k": "group", "v": "dev" }, { "k": "color", "v": "blue" } ] }, { "name": "User3", "tags": [ { "k": "group", "v": "dev" }, { "k": "color", "v": "red" } ] } ] and if you want to find out elements having "tags": [ { "k": "group", "v": "dev" }, { "k": "color", "v": "blue" } ] query : db.temp4.find({$and:[{"tags":{"k":"group","v":"dev"}},{"tags":{"k":"color","v":"blue"}}]}) and db.temp4.find({$and:[{"tags":{"$elemMatch":{"k":"group","v":"dev"}}},{"tags":{"$elemMatch":{"k":"color","v":"blue"}}}]}) in both case you will get response. Please help me to understand when to use $elemMatch and "$and". Thanks in advance. Sorry for grammatical mistakes.
The below query should work. As it is an embedded array, the "points.bonus" and "points.points" should be referred like this when $gte is used. db.collection.find({$and:[{"points":{"points":85,"bonus":20}}, {"points.points" : 64, "points.bonus" : {$gte : 10}}]}) In the second example, there is no $gte. So, you are getting response for both queries.
Multi-level sorting or orderBy in mongoDB
I am working on mongoDB with Laravel using jenssegers . and i am trying to get documents on sorting based on layout.price. Is this possible in mongodb with laravel. ? I am using limit and skip for pagination , so i have to get orderBy or sort direct from Database. [{ "title": "I am first document", "design": "mango", "description": "Loremipsum", "dimension": [ { "id": "542549383d1784901000002c" } ], "layout": [ { "id": "542411813d17849810000029", "price": NumberInt(69000) }, { "id": "542411813d17849810000030", "price": NumberInt(2000) } ], "images": [ "uploads/sofa/QRSTU695a6_0.png" ], "product_type": NumberInt(1), "updated_at": ISODate("2014-10-08T08:47:26.0Z"), "created_at": ISODate("2014-09-29T11:13:52.0Z") }, { "title": "I am second document", "design": "mango2", "description": "Loremipsum", "dimension": [ { "id": "542549383d1784901000002d" } ], "layout": [ { "id": "542411813d17849810000031", "price": NumberInt(80000) }, { "id": "542411813d17849810000032", "price": NumberInt(27000) } ], "images": [ "uploads/sofa/QRSTU695a6_0.png" ], "product_type": NumberInt(1), "updated_at": ISODate("2014-10-08T08:47:26.0Z"), "created_at": ISODate("2014-09-29T11:13:52.0Z") }]