I have two collections
Reports
{"brand": "Nike", "created": "2021-05-03T20:12:32.911000", "id": ObjectId("60929848088f18212809221c")}
Status
{"id": "60929848088f18212809221c", "report": ObjectId("60929848088f18212809221c"), "created": "2021-05-05T20:12:32.911000"}
I want to join these collections based on the report(in Status collection) - _id ( in Reports collection).
I tried the below query(The code here is complex because it does a few more things that are necessary to me):
query = [
{'$group': {'_id': '$_id', 'data': {'$last': '$$ROOT'}}},
{'$match': match},
{'$sort': {'data.created': pymongo.DESCENDING}},
{'$facet': {
'stage1': [{'$group': {'_id': None, 'count': {'$sum': 1}}}],
'stage2': [{'$skip': offset}, {'$limit': limit}]
}},
{'$unwind': '$stage1'},
{'$project': {
'count': '$stage1.count',
'data': '$stage2'
}},
{
"$lookup": {
"from": "status",
"localField": "data._id",
"foreignField": "report",
"as": "report"
}
}
]
I expect such a result:
[
{
"count": 3,
"data": [
{
"_id": ObjectId("5a934e000102030405000001"),
"data": {
"_id": ObjectId("5a934e000102030405000001"),
"brand": "Nike",
"created": "2021-05-03T20:12:32.911000",
},
"report": {
"_id": ObjectId("5a934e000102030405000003"),
"created": "2021-05-05T20:12:32.911000",
"id": "60929848088f18212809221c",
"report": ObjectId("5a934e000102030405000001")
},
},
}
]
}
]
I mean I mean it will be in every result
I tried to get help with that too but it did not work Here.
I'm using Mongo DB 4+
Related
I want count of all documents before doing grouping as show in my Query. The purpose of this if ai get count of all documents then I can calculate Percentage(%) of each individual students count. I tried with $count but after using that I'm not able to group my query. Is there any way 1st I can have counts of all documents after using $match function then store it to another variable without losing data.
This is the Query
const data = await AttendanceSchema.aggregate([
{ $match: { subjectID: mongoose.Types.ObjectId(`${req.params.Sid}`) } },
// Before Group I also want count of all documents
{ $group: { _id: "$studentID", count: { $sum: 1 } } },
{
$lookup: {
from: "students",
localField: "_id",
foreignField: "_id",
as: "student",
},
},
{
$project: {
"student.createdAt": 0,
"student.updatedAt": 0,
"student.__v": 0,
"student.password": 0,
},
},
]);
The data I'm getting from this query
{
"data": [
{
"_id": "635d40803352895afffdc294",
"count": 3,
"student": [
{
"_id": "635d40803352895afffdc294",
"name": "D R",
"email": "d#gmail.com",
"number": "9198998888",
"rollNumber": 202,
"departmentID": "635a8ca21444a47d65d32c1a",
"classID": "635a92141a081229013255b4",
"position": "Student"
}
]
},
{
"_id": "635eb8898dea5f437789b751",
"count": 4,
"student": [
{
"_id": "635eb8898dea5f437789b751",
"name": "V R",
"email": "v#gmail.com",
"number": "9198998899",
"rollNumber": 203,
"departmentID": "635a8ca21444a47d65d32c1a",
"classID": "635a92141a081229013255b4",
"position": "Student"
}
]
}
]
}
The desired output:
"data": [
{
"_id": "635d40803352895afffdc294",
"totalCount: 7, //This is what I want
"count": 3,
"student": [
{
"_id": "635d40803352895afffdc294",
"name": "D R",
"email": "d#gmail.com",
"number": "9198998888",
"rollNumber": 202,
"departmentID": "635a8ca21444a47d65d32c1a",
"classID": "635a92141a081229013255b4",
"position": "Student"
}
]
},
{
"_id": "635eb8898dea5f437789b751",
"totalCount: 7, //This is what I want
"count": 4,
"student": [
{
"_id": "635eb8898dea5f437789b751",
"name": "V R",
"email": "v#gmail.com",
"number": "9198998899",
"rollNumber": 203,
"departmentID": "635a8ca21444a47d65d32c1a",
"classID": "635a92141a081229013255b4",
"position": "Student"
}
]
}
]
}
You could add a few more stages to you aggregation pipeline to output what you want.
Here are the extra stages:
{
"$group": {
"_id": null,
"totalCount": {"$sum": "$count"},
"docs": {"$push": "$$ROOT"}
}
},
{
"$project": {
"docs": {
"$map": {
"input": "$docs",
"as": "doc",
"in": {
"$mergeObjects": [
"$$doc",
{"totalCount": "$totalCount"}
]
}
}
}
}
},
{"$unwind": "$docs"},
{"$replaceWith": "$docs"}
Try it on mongoplayground.net.
I'm new as MongoDB, I have 2 collections: User and Video with below structure. When user like a video, video's _id will be added to liked_videos on user collection. liked_videos is an array of _id
video collection
{
_id
mp4_url,
liked_count
}
User collection
{
_id,
username,
password,
liked_videos: [ // videos _id array ]
}
How do I query to get the user's liked videos? Like below?
[
{
_id: 1
mp4_url,
liked_count
},
{
_id: 2
mp4_url,
liked_count
},
...
]
Thank you
You need to use $lookup to join collections and $size to get the array size
db.video.aggregate([
{
"$lookup": {
"from": "user",
"localField": "_id",
"foreignField": "liked_videos",
"as": "join_video"
}
},
{
"$project": {
liked_count: {
$size: "$join_video"
}
}
}
])
Working Mongo playground
Try this way
db={
"video": [
{
"_id": 1,
"mp4_url": "url1",
"liked_count": 2,
"quantity": 2
},
{
"_id": 2,
"mp4_url": "url2",
"liked_count": 3,
"quantity": 1
},
{
"_id": 3,
"mp4_url": "url2",
"liked_count": 3,
"quantity": 4
}
],
"User": [
{
"_id": 1,
"username": "almonds",
"password": "pwd",
"Likedvideos": [
"aaa",
"ffff"
]
},
{
"_id": 2,
"username": "almonds",
"password": "pwd",
"Likedvideos": [
"qqq",
"bbbb"
]
},
{
"_id": 3,
"username": "almonds",
"password": "pwd",
"Likedvideos": [
"ccc",
"ffff"
]
},
{
"_id": 4,
"username": "almonds",
"password": "pwd",
"Likedvideos": [
"bbbb",
"ffff"
]
},
{
"_id": 5,
"username": "almonds",
"password": "pwd",
"Likedvideos": [
"qqq",
"ffff"
]
},
{
"_id": 6
}
]
}
Query :
db.video.aggregate([
{
$match: {
_id: 1
}
},
{
"$lookup": {
"from": "User",
"localField": "_id",
"foreignField": "_id",
"as": "data"
},
},
{
$unwind: "$data"
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$data",
"$$ROOT"
]
}
}
},
{
$project: {
data: 0
}
}
])
Output:
[
{
"Likedvideos": [
"aaa",
"ffff"
],
"_id": 1,
"liked_count": 2,
"mp4_url": "url1",
"password": "pwd",
"quantity": 2,
"username": "almonds"
}
]
mongoplayground
Let's say we have two collections, users and posts:
{
"users": [
{
"_id": 1,
"name": "John"
},
{
"_id": 2,
"name": "Jack"
},
{
"_id": 3,
"name": "Mike"
}
],
"posts": [
{
"_id": 1,
"text": "Post 1",
"userId": 1
},
{
"_id": 2,
"text": "Post 2",
"userId": 1
},
{
"_id": 3,
"text": "Post 3",
"userId": 2
}
]
}
Now, the question is as follows:
How can I write a query to filter out users (using aggregation pipeline or something else) depending on whether they have posts? For example, my query should only return an array of users with _id 1 and 2, not 3. Because, there are no posts with userId: 3;
$lookup join posts collection
$match is return post is not empty
$project to remove post field if its not needed
db.users.aggregate([
{
"$lookup": {
"from": "posts",
"localField": "_id",
"foreignField": "userId",
"as": "post"
}
},
{ $match: { post: { $ne: [] } } },
{ $project: { post: 0 } }
])
Playground
I have two collections, users and posts. The relevant parts of a typical document looks like this:
user
{
"_id": "user1",
"name": "Joe",
"age": 20
}
posts
{
"content": "Yo what's up!",
"created": "2018-02-05T05:00:00.000Z",
"author": "user1"
}
I would like to create a query on the posts collection that returns the following:
{
"content": "Yo what's up!",
"created": "2018-02-05T05:00:00.000Z",
"author": {
"name": "Joe",
"age": 20
}
Is there any way to do this in raw MongoDB?
I'm using the MongoDB Node.js client.
Using aggregation with lookup operator.
db.posts.aggregate([
{"$lookup":{
"from":"users",
"localField":"author",
"foreignField":"_id",
"as":"author"
}},
{"$addFields":{
"author": {"$arrayElemAt":["$author",0]}
}}])
db.posts.aggregate(
// Pipeline
[
// Stage 1
{
$lookup: {
"from": "user",
"localField": "author",
"foreignField": "_id",
"as": "authorobj"
}
},
// Stage 2
{
$project: {
content: 1,
created: 1,
author: {
'name': {
"$arrayElemAt": ["$authorobj.name", 0]
},
'age': {
"$arrayElemAt": ["$authorobj.age", 0]
}
},
}
},
]
);
I have query like this:
{"$match": {$or: [{"to": system.mongoose.Types.ObjectId(userId)}, {"from": system.mongoose.Types.ObjectId(userId)}]}},
{"$sort": {"createDate": -1}},
{
"$group": {
"_id": "$conversationId",
"from": {"$first": "$from"},
"to": {"$first": "$to"},
"content": {"$first": "$content"},
"createDate": {"$first": "$createDate"},
"unreaded": {"$sum": {"$cond":
{if :
{
$and: [
{
"$eq": [
"$unreaded", 1
]
},
{
"$eq": ["$to", system.mongoose.Types.ObjectId(userId)]
}
]
}, then: 1, else: 0}}}
unreaded will return unreaded messages for each conversation, how can I get sum of all unreaded messages?