Several $lookup in a single MongoDB query - mongodb

I am currently creating a request, but I can not.
So there is one the document of 1 user:
"_id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"search" : "flarize",
"name" : "flarize",
"email" : "flarize.a473#gmail.com",
"password" : "$2a$10$eYeOtEkEUyD7TFkjKvhZOuSSpvBolkL17TrPHuoHhOT8JrsQR0UKW",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 1540501286109,
"friend" : [
{
"id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"date" : 1540713424488
}
]
And my query:
db.users.aggregate([{
$match:{
search: "flarize"
}},{
$lookup:{
from: "users",
let:{friendId:"$friend.id"},
pipeline:[{
$match:{
$expr:{
$in:["$_id","$$friendId"]
}
}},{
$limit:10},{
$skip:0},{
$project: {
name: 1,
search:1,
desc:1,
friend:1,
date:1,
banner:1,
profil:1,
color: 1
}
}],
as:"friends"}},{
$project:{
profil:1,
search:1,
name:1,
profile:1,
banner:1,
color:1,
date:1,
desc:1,
friend:1,
friends:1
}
}]).pretty();
I got this result:
{
"_id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"search" : "flarize",
"name" : "flarize",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 1540501286109,
"friend" : [
{
"id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"date" : 1540713424488
}
],
"friends" : [
{
"_id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"search" : "flarize",
"name" : "flarize",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 1540501286109,
"friend" : [
{
"id" : ObjectId("5bd22f28f77cfb1f6ce503ca"),
"date" : 1540713424488
}
]
}
]
}
It's not really what I want.I would like Compare the document of the selection person, and the one who requests the query if the id of the person selected is present in friend then is_friend will be equal to true otherwise it will be equal to false.
I try this think:
db.users.aggregate([{
$match:{
search: "flarize"
}},{
$lookup:{
from: "users",
let:{friendId:"$friend.id"},
pipeline:[{
$match:{
$expr:{
$in:["$_id","$$friendId"]
}
}},{
$limit:10},{
$skip:0},{
$project: {
name: 1,
search:1,
desc:1,
friend:1,
date:1,
banner:1,
profil:1,
color: 1
is_friend:{
$lookup:{
from:"users",
let:{friendIdIs:"$_id"},
pipeline:[{
$match:{
$expr:{
$and:[{
$in:["$$friendIdIs", "$friend.is"]},{
$eq:["_id", ObjectId("5bd22f28f77cfb1f6ce503ca")]
}]
}
}
}],
as:"yes"}}
}
}
}],
as:"friends"}},{
$project:{
profil:1,
search:1,
name:1,
profile:1,
banner:1,
color:1,
date:1,
desc:1,
friend:1,
friends:1
}
}]).pretty();
But it's don't work.
Thank you for helping me

Related

How to join 2 collections if the ID types in 1st collection is ObjectId and the foreign key type is string in mongodb

I have 2 collections,1st is:
{
"_id" : ObjectId("62eb5713ac2dccfb0a75d6c0"),
"title" : "Agile Web Development with Rails",
"categoryId" : ObjectId("62eb5713ac2dccfb0a75d6bf"),
"subtitle" : "Dive into ES6 and the Future of JavaScript",
"author" : "Sam Ruby, Dave Thomas, David Heinemeier Hansson",
"published" : 2010,
"publisher" : "O'Reilly Media",
"isActive" : true,
"isDelete" : false,
"__v" : 0
}
{
"_id" : ObjectId("62eb5777ac2dccfb0a75d6c3"),
"title" : "Eloquent JavaScript, Third Edition",
"categoryId" : ObjectId("62eb5777ac2dccfb0a75d6c2"),
"subtitle" : "A Modern Introduction to Programming",
"author" : "Marijn Haverbeke",
"published" : 2018,
"publisher" : "No Starch Press",
"isActive" : true,
"isDelete" : false,
"__v" : 0
}
{
"_id" : ObjectId("62eb5aa0e45707fec304e115"),
"title" : "Eloquent JavaScript, Third Edition",
"categoryId" : ObjectId("62eb41f088b1bc88e8a416db"),
"subtitle" : "A Modern Introduction to Programming",
"author" : "Marijn Haverbeke",
"published" : 2018,
"publisher" : "No Starch Press",
"isActive" : true,
"isDelete" : false,
"__v" : 0
}
{
"_id" : ObjectId("62ebaf20de65e74cd055565a"),
"title" : "Rethinking Productivity in Software Engineering",
"categoryId" : ObjectId("62eb420b88b1bc88e8a416df"),
"subtitle" : "Everything you neeed to know about Gi",
"author" : "Caitlin Sadowski, Thomas Zimmermann",
"published" : 2019,
"publisher" : "Apress",
"isActive" : true,
"isDelete" : false,
"__v" : 0
}
{
"_id" : ObjectId("62f08a12e0346e06e4bb7b06"),
"categoryId" : ObjectId("62f08a12e0346e06e4bb7b05"),
"isActive" : true,
"isDelete" : false,
"__v" : 0
}
2nd collection is:
{
"_id" : ObjectId("62f3377166def37dee13f400"),
"book_id" : "62eb5713ac2dccfb0a75d6c0",
"description" : "for Agile Web..."
}
{
"_id" : ObjectId("62f3383566def37dee13f401"),
"book_id" : "62ebaf20de65e74cd055565a",
"description" : "for Rethinking Productivity..."
}
{
"_id" : ObjectId("62f3388666def37dee13f402"),
"book_id" : "62eb5aa0e45707fec304e115",
"description" : "for Eloquent JavaScript..."
}
I want to join 2 collections by use of aggregate $lookup,$match,$and,$ecpr,$eq and get the data in Mongo compass by using 'pipe line from text'. My code is:
[{$lookup:
({
from: "books",
let: {
"bkid": new mongoose.Types.ObjectId('book_id')
},
pipeline: [{
$match: {
$and: {
$expr: {
$eq: ['$_id', '$$bkid']
}
}
}
}],
as: "res"
})
}]
What is wrong here why its not showing output?
I am doing this code in Mongodbaggregation -> CREATE -> Pipeline for Text.
Thanks in advance.
It can be possible by two ways i.e,
1.by converting id type ObjectId to string
db.books.aggregate({
"$project": {
"_id": {
"$toString": "$_id"
}
}
},
{
"$lookup": {
"from": "description",
"localField": "_id",
"foreignField": "book_id",
"as": "result"
}
})
2.by converting string to ObjectId
db.description.aggregate([
{
$lookup: {
from: "books",
let: { bkid: {$convert: {input: '$book_id', to : 'objectId', onError: 'error',onNull: 'null'}} },
pipeline: [{
$match: {
$and: [
{ $expr: { $eq: ['$_id', '$$bkid'] } }
],
}
}],
as: "result"
}
}
])

Mongodb match with multiple condition not working

I have user collection having data like this
{
"_id" : ObjectId("5da594c15324fec81d000027"),
"password" : "******",
"activation" : "Active",
"userType" : "Author",
"email" : "something#gmail.com",
"name" : "Something",
"profilePicture" : "profile_pictures/5da594c15324fec81d0000271607094354423image.png",
"__v" : 0
}
On the other hand userlog has data like this
{
"_id" : ObjectId("5fcb7bb4485c34a41900002b"),
"duration" : 2.54,
"page" : 1,
"activityDetails" : "Viewed Page for seconds",
"contentType" : "article",
"activityType" : "articlePageStayTime",
"bookId" : ObjectId("5f93e2cc74153f8c1800003f"),
"ipAddress" : "::1",
"creator" : ObjectId("5da594c15324fec81d000027"),
"created" : ISODate("2020-12-05T12:23:16.867Z"),
"__v" : 0
}
What I need is data like below
{
"_id" : ObjectId("5da594c15324fec81d000027"),
"password" : "******",
"activation" : "Active",
"userType" : "Author",
"email" : "something#gmail.com",
"name" : "Something",
"profilePicture" : "profile_pictures/5da594c15324fec81d0000271607094354423image.png",
"userlogs":
[{
"_id" : ObjectId("5fcb7bb4485c34a41900002b"),
"duration" : 2.54,
"page" : 1,
"activityDetails" : "Viewed Page for seconds",
"contentType" : "article",
"activityType" : "articlePageStayTime",
"bookId" : ObjectId("5f93e2cc74153f8c1800003f"),
"ipAddress" : "::1",
"creator" : ObjectId("5da594c15324fec81d000027"),
"created" : ISODate("2020-12-05T12:23:16.867Z"),
"__v" : 0
}]
}
I am trying to find all the user except admin with their log for each month. So my condition is user wont be admin and date will be between two range. But it is not working. My current code is below which is returning empty dataset-
User
.aggregate([
{
$match: {
userType: {
$ne:"admin"
}
},
"$and": [
{
"userlogs.created": {
$lte: dateCompare.end
}
},
{
"userlogs.created": {
$gte: dateCompare.start
}
}
]
},
{
$lookup:{
from: "userlogs", //or Races.collection.name
localField: "_id",
foreignField: "creator",
as: "userlogs"
},
},
]
I am using mongodb version 3.2
Try this
User.aggregate([
{
$match: {
userType: {
$ne:"admin"
}
},
{
$graphLookup:{
from: "userlogs", //or Races.collection.name
startWith: "$_id",
connectToField:"creator",
connectFromField:"_id",
maxDepth:0,
as: "userlogs",
restrictSearchWithMatch:{created:{
$lte:dateCompare.end,
$gte:dateCompare.start
}}
},
} ]

Whats the alternative to $replaceRoot on mongoDB? $replaceRoot is incompatible with documentDB

The problem: I'm trying to make a query on MongoDB, but I'm using the DocumentDb from amazon, where some operations are no supported. I wanted to find an alternative to get the same result, if possible. Basically I want to change the root of the result, instead of being the first entity, I need it to be some merging of some values in different levels of the document.
So, I have the following structure in my collection:
{
"_id" : ObjectId("5e598bf4d98f7c70f9aa3b58"),
"status" : "active",
"invoices" : [
{
"_id" : ObjectId("5e598bf13b24713f50600375"),
"value" : 1157.52,
"receivables" : [
{
"situation" : {
"status" : "active",
"reason" : []
},
"rec_code" : "001",
"_id" : ObjectId("5e598bf13b24713f50600374"),
"expiration_date" : ISODate("2020-03-25T00:00:00.000Z"),
"value" : 1157.52
}
],
"invoice_code" : 9773,
"buyer" : {
"legal_name" : "test name",
"buyer_code" : "223132165498797"
}
},
],
"seller" : {
"code" : "321654897986",
"name" : "test name 2"
}
}
What I want to achieve is to list all "receivables" like this, where the _id is the _id of the receivable:
[{
"_id" : ObjectId("5e598bf13b24713f50600374"),
"situation" : {
"status" : "active",
"reason" : []
},
"rec_code" : "001",
"expiration_date" : ISODate("2020-03-25T00:00:00.000Z"),
"value" : 1157.52,
"status" : "active",
"seller" : {
"cnpj" : "321654897986",
"name" : "test name 2"
},
"invoice_code" : 9773.0,
"buyer" : {
"legal_name" : "test name",
"cnpj" : "223132165498797"
}
}]
This I can do with $replaceRoot in with the query below on MongoDB, but using documentDB I can't use $replaceRoot or $mergeObjects. Do you know how can I get the same result with other operators?:
db.testCollection.aggregate([
{ $unwind: "$invoices" },
{ $replaceRoot: {
newRoot: {
$mergeObjects: ["$$ROOT","$invoices"]}
}
},
{$project: {"_id": 0, "value": 0, "created_at": 0, "situation": 0}},
{ $unwind: "$receivables" },
{ $replaceRoot: {
newRoot: {
$mergeObjects: ["$receivables", "$$ROOT"]
}
}
},
{$project:{"created_at": 0, "receivables": 0, "invoices": 0}}
])
After going through mongodb operations, I could get a similar result fro what I wanted with the following query without $replaceRoot. It turns out it was a better query, I think:
db.testCollection.aggregate([
{$unwind: "$invoices"},
{$project : {
created_at: 1,
seller: "$seller",
buyer: "$invoices.buyer",
nnf: "$invoices.nnf",
receivable: '$invoices.receivables'
}
},
{$unwind: "$receivable"},
{$project : {
_id: '$receivable._id',
seller: 1,
buyer: 1,
invoice_code: 1,
receivable: 1,
created_at: 1,
}
},
{$sort: {"created_at": -1}},
])
This query resulted in the following structure list:
[{
"created_at" : ISODate("2020-03-06T09:47:26.161Z"),
"seller" : {
"name" : "Test name",
"cnpj" : "21231232131232"
},
"buyer" : {
"cnpj" : "21322132164654",
"legal_name" : "Test name 2"
},
"invoice_code" : 66119,
"receivable" : {
"rec_code" : "001",
"_id" : ObjectId("5e601bb5efff82b92935bad4"),
"expiration_date" : ISODate("2020-03-17T00:00:00.000Z"),
"value" : 6540.7,
"situation" : {
"status" : "active",
"reason" : []
}
},
"_id" : ObjectId("5e601bb5efff82b92935bad4")
}]
Support for $replaceRoot was added to Amazon DocumentDB in January 2021.

Nested lookup in mongo db query

I am making a airline dummy webside, and i need get all sold tickets per flight for all airlines, i have 3 collections: airlines, flights and sales
I tried using a nested lookups in mongodb query, but i cant sum the total tickets, here is the current query and the result:
Airline.aggregate([{
$lookup: {
from: "flights",
localField: "id_airline",
foreignField: "id_airline",
as: "flights"
}
}, {
$unwind: {
path: "$flights",
preserveNullAndEmptyArrays: true
}
}, {
$lookup: {
from: "sales",
localField: "flights.id_flight",
foreignField: "id_flight",
as: "flights.sales",
}
}, {
$group: {
_id : "$_id",
idAirline: { $first: "$id_airline" },
flights: { $push: "$flights" }
}
}, {
$project: {
_id: 1,
idAirline: 1,
"flights.id_flight": 1,
"flights.price": 1,
"flights.sold":{$sum:"$flights.sales.tickets"}
}
}]
And the result is:
... },
{
"_id": "5db381cb18518043c40e3ecd",
"idAirline": "AVI-242",
"flights": [
{
"id_flight": "CPA-001",
"price": "125",
"sold": 0
},
{
"id_flight": "CGA-002",
"price": "150",
"sold": 0
},
{
"id_flight": "CHA-003",
"price": "135",
"sold": 0
}
]
},
....
Actually the fligth CPA-001 has 6 tickets sold but i cant sum a get the result.
Here are the documents:
Airlines
{"_id":{"$oid":"5db3823718518043c40e3ece"},"country":["Panamá","El Salvador","Belice"],"id_airline":"VOL-643","name_airport":"Juan Santamaría","name_airline":"Volaris","createdAt":{"$date":{"$numberLong":"1572045367094"}},"updatedAt":{"$date":{"$numberLong":"1572045367094"}},"__v":{"$numberInt":"0"}}
Flights
{"_id":{"$oid":"5db9a225154a1b1b08cc77c3"},"restrictions":["No Liquids"],"features":[],"id_flight":"CPA-001","id_airline":"AVI-242","date_departure":{"$date":{"$numberLong":"1546300800000"}},"date_arrival":{"$date":{"$numberLong":"1559779200000"}},"name":"CosPan","origin":"Costa Rica","destination":"Panamá","itinerary":"50 breakfasts","price":"125","status":"On Time","max_capacity":"50","createdAt":{"$date":{"$numberLong":"1572446757327"}},"updatedAt":{"$date":{"$numberLong":"1572447464367"}},"__v":{"$numberInt":"0"}}
Sales
{"_id":{"$oid":"5db9b643b50c0d1540b8db89"},"id_user":"304780391","id_flight":"CPA-001","origin":"Costa Rica","destination":"Panamá","date_departure":{"$date":{"$numberLong":"1546300800000"}},"date_arrival":{"$date":{"$numberLong":"1559779200000"}},"tickets":{"$numberInt":"4"},"suitcases":{"$numberInt":"1"},"status":"Bought","seat":{"$numberInt":"-1"},"createdAt":{"$date":{"$numberLong":"1572451907375"}},"updatedAt":{"$date":{"$numberLong":"1572451907375"}},"__v":{"$numberInt":"0"}}
I think the nested arrays are causing some difficulties. I added another $unwind between $lookup and $group. Let me know what you think...
db.airlines.aggregate([
{ $lookup: {
from: "flights",
localField: "id_airline",
foreignField: "id_airline",
as: "flights"
}
},
{ $unwind: {
path: "$flights",
preserveNullAndEmptyArrays: true
}
},
{ $lookup: {
from: "sales",
localField: "flights.id_flight",
foreignField: "id_flight",
as: "flights.sales",
}
},
{ $unwind: {
path: "$flights.sales",
preserveNullAndEmptyArrays: true
}
},
{ $group: {
_id : "$_id",
idAirline: { $first: "$id_airline" },
flights: { $push: "$flights" }
}
},
{ $project: {
_id: 1,
idAirline: 1,
"flights.id_flight": 1,
"flights.price": 1,
"flights.sold":{$sum: "$flights.sales.tickets"}
}
}
]).pretty()
Documents used to test:
flights
{
"_id" : ObjectId("5db9a225154a1b1b08cc77c3"),
"restrictions" : [
"No Liquids"
],
"features" : [ ],
"id_flight" : "CPA-001",
"id_airline" : "VOL-643",
"date_departure" : ISODate("2019-10-30T23:04:17.119Z"),
"date_arrival" : ISODate("2019-10-30T23:04:17.119Z"),
"name" : "CosPan",
"origin" : "Costa Rica",
"destination" : "Panamá",
"itinerary" : "50 breakfasts",
"price" : "125",
"status" : "On Time",
"max_capacity" : "50",
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
}
airlines
{
"_id" : ObjectId("5db3823718518043c40e3ece"),
"country" : [
"Panamá",
"El Salvador",
"Belice"
],
"id_airline" : "VOL-643",
"name_airport" : "Juan Santamaría",
"name_airline" : "Volaris",
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
}
sales
[{
"_id" : ObjectId("5db9b643b50c0d1540b8db89"),
"id_user" : "304780391",
"id_flight" : "CPA-001",
"origin" : "Costa Rica",
"destination" : "Panamá",
"date_departure" : ISODate("2019-10-30T23:04:17.119Z"),
"date_arrival" : ISODate("2019-10-30T23:04:17.119Z"),
"tickets" : 4,
"suitcases" : {
"$numberInt" : "1"
},
"status" : "Bought",
"seat" : -1,
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
},
{
"_id" : ObjectId("5db9b643b50c0d1540b8db8a"),
"id_user" : "304780391",
"id_flight" : "CPA-001",
"origin" : "Costa Rica",
"destination" : "Panamá",
"date_departure" : ISODate("2019-10-30T23:04:17.119Z"),
"date_arrival" : ISODate("2019-10-30T23:04:17.119Z"),
"tickets" : 4,
"suitcases" : {
"$numberInt" : "1"
},
"status" : "Bought",
"seat" : -1,
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
}]

Problems aggregating MongoDB

I am having problems aggregating my Product Document in MongoDB.
My Product Document is:
{
"_id" : ObjectId("5d81171c2c69f45ef459e0af"),
"type" : "T-Shirt",
"name" : "Panda",
"description" : "Panda's are cool.",
"image" : ObjectId("5d81171c2c69f45ef459e0ad"),
"created_at" : ISODate("2019-09-17T18:25:48.026+01:00"),
"is_featured" : false,
"sizes" : [
"XS",
"S",
"M",
"L",
"XL"
],
"tags" : [ ],
"pricing" : {
"price" : 26,
"sale_price" : 8
},
"categories" : [
ObjectId("5d81171b2c69f45ef459e086"),
ObjectId("5d81171b2c69f45ef459e087")
],
"sku" : "5d81171c2c69f45ef459e0af"
},
And my Category Document is:
{
"_id" : ObjectId("5d81171b2c69f45ef459e087"),
"name" : "Art",
"description" : "These items are our artsy options.",
"created_at" : ISODate("2019-09-17T18:25:47.196+01:00")
},
My aim is to perform aggregation on the Product Document in order to count the number of items within each Category. So I have the Category "Art", I need to count the products are in the "Art" Category:
My current aggregate:
db.product.aggregate(
{ $unwind : "$categories" },
{
$group : {
"_id" : { "name" : "$name" },
"doc" : { $push : { "category" : "$categories" } },
}
},
{ $unwind : "$doc" },
{
$project : {
"_id" : 0,
"name" : "$name",
"category" : "$doc.category"
}
},
{
$group : {
"_id" : "$category",
"name": { "$first": "$name" },
"items_in_cat" : { $sum : 1 }
}
},
{ "$sort" : { "items_in_cat" : -1 } },
)
Which does actually work but not as I need:
{
"_id" : ObjectId("5d81171b2c69f45ef459e082"),
"name" : null, // Why is the name of the category no here?
"items_in_cat" : 4
},
As we can see the name is null. How can I aggregate the output to be:
{
"_id" : ObjectId("5d81171b2c69f45ef459e082"),
"name" : "Art",
"items_in_cat" : 4
},
We need to use $lookup to fetch the name from Category collection.
The following query can get us the expected output:
db.product.aggregate([
{
$unwind:"$categories"
},
{
$group:{
"_id":"$categories",
"items_in_cat":{
$sum:1
}
}
},
{
$lookup:{
"from":"category",
"let":{
"id":"$_id"
},
"pipeline":[
{
$match:{
$expr:{
$eq:["$_id","$$id"]
}
}
},
{
$project:{
"_id":0,
"name":1
}
}
],
"as":"categoryLookup"
}
},
{
$unwind:{
"path":"$categoryLookup",
"preserveNullAndEmptyArrays":true
}
},
{
$project:{
"_id":1,
"name":{
$ifNull:["$categoryLookup.name","NA"]
},
"items_in_cat":1
}
}
]).pretty()
Data set:
Collection: product
{
"_id" : ObjectId("5d81171c2c69f45ef459e0af"),
"type" : "T-Shirt",
"name" : "Panda",
"description" : "Panda's are cool.",
"image" : ObjectId("5d81171c2c69f45ef459e0ad"),
"created_at" : ISODate("2019-09-17T17:25:48.026Z"),
"is_featured" : false,
"sizes" : [
"XS",
"S",
"M",
"L",
"XL"
],
"tags" : [ ],
"pricing" : {
"price" : 26,
"sale_price" : 8
},
"categories" : [
ObjectId("5d81171b2c69f45ef459e086"),
ObjectId("5d81171b2c69f45ef459e087")
],
"sku" : "5d81171c2c69f45ef459e0af"
}
Collection: category
{
"_id" : ObjectId("5d81171b2c69f45ef459e086"),
"name" : "Art",
"description" : "These items are our artsy options.",
"created_at" : ISODate("2019-09-17T17:25:47.196Z")
}
{
"_id" : ObjectId("5d81171b2c69f45ef459e087"),
"name" : "Craft",
"description" : "These items are our artsy options.",
"created_at" : ISODate("2019-09-17T17:25:47.196Z")
}
Output:
{
"_id" : ObjectId("5d81171b2c69f45ef459e087"),
"items_in_cat" : 1,
"name" : "Craft"
}
{
"_id" : ObjectId("5d81171b2c69f45ef459e086"),
"items_in_cat" : 1,
"name" : "Art"
}