Mongoose lookup returning wrong result - mongodb

I have two schemas:
const userSchema = new Schema(
{
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
},
{
timestamps: true,
}
);
const userLikeSchema = new Schema(
{
userId: {
type: String,
required: true,
ref: 'User',
},
likedUserId: {
type: String,
required: true,
ref: 'User',
},
isActive: {
type: Boolean,
required: true,
default: true,
},
},
{
timestamps: true,
}
);
I am trying to get a list of users ordered descending by their number of likes.
I am not sure if the schema I did sql-like is correct.
I have written the following query:
const likedUsers = await UserLike.aggregate(
[
{
$group: {
_id: '$likedUserId',
likes: { $sum: 1 },
},
},
{ $sort: { likes: -1 } },
{
$lookup: {
from: 'users',
localField: 'likedUserId',
foreignField: '_id.str',
as: 'user',
},
},
]
);
I am trying to get a result like:
[
{
"_id": "604bb648be8680063009fddc",
"likes": 2,
"user": {
"_id": "604bb648be8680063009fddc",
"username": "muhamed",
"password": "$2b$10$EVYWZb4vl2TFGmIrCWe1sO/QogdU6/Ui8TgujY4PMKLJKIVOzmOi6",
"createdAt": "2021-03-12T18:43:20.806Z",
"updatedAt": "2021-03-12T18:46:17.635Z",
"__v": 0
},
}
]
But instead I am getting the following which shows every user for each item:
[
{
"_id": "604bb648be8680063009fddc",
"likes": 2,
"user": [
{
"_id": "604bb648be8680063009fddc",
"username": "muhamed",
"password": "$2b$10$EVYWZb4vl2TFGmIrCWe1sO/QogdU6/Ui8TgujY4PMKLJKIVOzmOi6",
"createdAt": "2021-03-12T18:43:20.806Z",
"updatedAt": "2021-03-12T18:46:17.635Z",
"__v": 0
},
{
"_id": "604bc703ea4bf93fb427056a",
"username": "krasniqi",
"password": "$2b$10$dnKumHhKNIfA6BM3uekymOpIdMFuQy9aYYKmGBxnW401CjTAuMLIy",
"createdAt": "2021-03-12T19:54:43.368Z",
"updatedAt": "2021-03-12T19:54:43.368Z",
"__v": 0
},
{
"_id": "604c90ab9f7b970cd46ff668",
"username": "matin",
"password": "$2b$10$CEUCaGk.JF5PBwsTBE3fRufVXzUBt.eLyo28eTt8zhBezVSFflMhS",
"createdAt": "2021-03-13T10:15:07.877Z",
"updatedAt": "2021-03-13T10:15:07.877Z",
"__v": 0
}
]
},
]
What am I missing ?

I think there is an issue about _id.str.
You have set your userLikeSchema wrong. You should have set the type of your ID fields mongoose.Schema.ObjectId:
const userLikeSchema = new Schema(
{
userId: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'User',
},
likedUserId: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'User',
},
isActive: {
type: Boolean,
required: true,
default: true,
},
},
{
timestamps: true,
}
);
After that, you can easily lookup by _id:
const likedUsers = await UserLike.aggregate(
[
{
$group: {
_id: '$likedUserId',
likes: { $sum: 1 },
},
},
{ $sort: { likes: -1 } },
{
$lookup: {
from: 'users',
localField: '_id',
foreignField: '_id',
as: 'user',
},
}, {
$unwind: "$user"
}
]
);
As a result of $lookup you will get an array of user, so you need to use $unwind to get a single User object.
Result will be like:
{
"_id": "604bb648be8680063009fddc",
"likes": 2,
"user": {
"_id": "604bb648be8680063009fddc",
"username": "muhamed",
"password": "$2b$10$EVYWZb4vl2TFGmIrCWe1sO/QogdU6/Ui8TgujY4PMKLJKIVOzmOi6",
"createdAt": "2021-03-12T18:43:20.806Z",
"updatedAt": "2021-03-12T18:46:17.635Z",
"__v": 0
},
}

Related

MongoDB, return selected fields from document with aggregation operations

With given query I also want to return productId.
I have collection comments that contains documents with data about productId and comments for given product
Example document in this collection:
{
"_id": {
"$oid": "635ee64f55460d1796447662"
},
"productId": "63413800d36ed477adc763d0",
"__v": 0,
"comments": [
{
"userId": "",
"userName": "test",
"date": "2022.12.18.21.51.36",
"confirmed": false,
"likes": {
"up": 0,
"down": 0
},
"content": {
"rating": 6,
"description": "testtesttest"
},
"image": {
"added": false,
"images": []
},
"_id": {
"$oid": "639f7d58b6206a863c4a7aba"
},
"usersWhoLiked": []
},
{
"userId": "",
"userName": "test",
"date": "2022.12.18.21.52.19",
"confirmed": false,
"likes": {
"up": 0,
"down": 0
},
"content": {
"rating": 6,
"description": "testtesttest"
},
"image": {
"added": true,
"images": [
"comments/63413800d36ed477adc763d0/639f7d83b6206a863c4a7ad6/dell.jpg"
]
},
"_id": {
"$oid": "639f7d83b6206a863c4a7ad6"
},
"usersWhoLiked": []
}
]
}
My exmaple query:
db.comments.aggregate([{$match: {"comments._id": {$in: [ObjectId('630b7868f51e10876223b4aa'), ObjectId('630bd277f919a9e9c0e7a559')]}}},
{$project: {comment: {$filter: {input: "$comments", as: "comment", cond: {$in: ["$$comment._id", [ObjectId("630b7868f51e10876223b4aa"), ObjectId("630bd277f919a9e9c0e7a559")]]}}}}}])
With this query I get the result :
{ _id: ObjectId("630b7868f51e10876223b4a6"),
comment:
[ { userId: '62f29c2c324f4778dff443f6',
userName: 'User',
date: '2022.08.19',
confirmed: false,
likes: { up: 3, down: 0 },
content: { rating: 4, description: 'Super laptop <3' },
_id: ObjectId("630b7868f51e10876223b4aa"),
usersWhoLiked:
[ { userId: '62f29c2c324f4778dff443f6',
likeUp: true,
_id: ObjectId("630d2b0494370efb37107983") },
{ userId: '6322434f2b5bbac87f0e7aba',
likeUp: true,
_id: ObjectId("632243702b5bbac87f0e7afa") },
{ userId: '62f2991e324f4778dff443d4',
likeUp: true,
_id: ObjectId("63af4d77c8991b74d6986995") } ] } ] }
{ _id: ObjectId("630bd277f919a9e9c0e7a555"),
comment:
[ { userId: '62f29c2c324f4778dff443f6',
userName: 'User',
date: '2022.08.28',
confirmed: false,
likes: { up: 1, down: 1 },
content:
{ rating: 6,
description: 'Laptop posiada przyjemna klawiature, nie grzeje siÄ™. Do codziennego grania wystarczy.' },
_id: ObjectId("630bd277f919a9e9c0e7a559"),
usersWhoLiked:
[ { userId: '62f29c2c324f4778dff443f6',
likeUp: true,
_id: ObjectId("630d2dfc94370efb37107991") },
{ userId: '62fa2549f029348f75bc9c81',
likeUp: false,
_id: ObjectId("631241fe755c641525dc9cfa") } ] } ] }
As you see in the result, the productId is missing.
I was trying to rebuild query with #group operator but still with out effect...
So my questsion is:
How shall I rewrite that query to get the same result but with productId in it for each returned comment
This is how $project works, if a field is not specified will not be output.
So just add productId: 1 into the $project stage and it will be shown.
Check this example.

MongoDB Aggregation - Select only same value from array inside lookup

I have aggregation like this:
Produk.aggregate([
{
$lookup: {
from: "kis_m_kategoriproduks",
localField: "idSubKategori",
foreignField: "subKategori._id",
as: "kategori",
},
},
{ $unwind: "$kategori" },
{ $sort: { produk: 1 } },
{
$project: {
_id: 0,
id: "$id",
dataKategori: {
idKategori: "$kategori._id",
kategori: "$kategori.kategori",
idSubKategori: "$idSubKategori",
subKategori: "$kategori.subKategori",
},
},
},
])
current result is :
{
"status": "success",
"data": [
{
"dataKategori": {
"idKategori": "6195bbec8ee419e6a9b8329d",
"kategori": "Kuliner",
"idSubKategori": "6195bc0f8ee419e6a9b832a2",
"subKategori": [
{
"nama": "Food",
"_id": "6195bc0f8ee419e6a9b832a2"
},
{
"nama": "Drink",
"_id": "6195bc258ee419e6a9b832a8"
}
]
}
}
]
}
I only want to display data in subKategori that the _id match with idSubKategori. this what I expected:
{
"status": "success",
"data": [
{
"dataKategori": {
"idKategori": "6195bbec8ee419e6a9b8329d",
"kategori": "Kuliner",
"idSubKategori": "6195bc0f8ee419e6a9b832a2",
"subKategori": [
{
"nama": "Food",
"_id": "6195bc0f8ee419e6a9b832a2"
}
]
}
}
]
}
here is my $kategori schema:
const schema = mongoose.Schema(
{
kategori: {
type: String,
required: true,
unique: true,
},
subKategori: [
{
id: mongoose.Types.ObjectId,
nama: String,
},
],
},
{
timestamps: false,
}
);
any suggestion?
I fix the problem by add $filter inside $project like this:
dataKategori: {
idKategori: "$kategori._id",
kategori: "$kategori.kategori",
subKategori: {
$arrayElemAt: [
{
$filter: {
input: "$kategori.subKategori",
as: "sub",
cond: { $eq: ["$$sub._id", "$idSubKategori"] },
},
},
0,
],
},
},
reference: https://stackoverflow.com/a/42490320/6412375

aggregation with group by, inner join and nested conditions in MongoDB

First of all I am sorry if this is a basic question, I am new to queries in MongoDB. Well, what I need is to find the latest registers for a worker in my WorkerLocationContext document and the latest register for each sensor in my HeatMeasureContext document, then join it by their location and then apply some filters. Here are my Schemas:
HeatMeasureContext:
const heatMeasureContextSchema = new mongoose.Schema({
sensor: { type: Schema.Types.ObjectId, ref: 'MeasureSensor', required: true },
humid: { type: Schema.Types.Number, required: true },
globe: { type: Schema.Types.Number, required: true },
mercury: { type: Schema.Types.Number, required: true },
internal: { type: Schema.Types.Number, required: true },
external: { type: Schema.Types.Number, required: true }
}, { timestamps: true })
MeasureSensor:
const measureSensorSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: false },
type: { type: String, required: false, uppercase: true,
enumValues: ['MEASURE'], default: 'MEASURE' },
location: { type: Schema.Types.ObjectId, ref: 'Location' },
sensorType: { type: String, required: false, uppercase: true,
enumValues: ['WORKER_ATTACHED', 'ENVIRONMENT'], default: 'ENVIRONMENT' },
measurerType: { type: String, required: false, uppercase: true,
enumValues: ['HEAT', 'RUID'] },
placementType: { type: String, required: false, uppercase: true,
enumValues: ['INTERNAL', 'EXTERNAL'], default: 'INTERNAL' }
})
WorkerLocationContext:
const workerLocationContextSchema = new mongoose.Schema({
sensor: { type: Schema.Types.ObjectId, ref: 'LocationSensor', required: true },
worker: { type: Schema.Types.ObjectId, ref: 'Worker', required: true }
}, { timestamps: true })
Location
const locationSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: false },
type: { type: String, required: false, uppercase: true,
enumValues: ['REST', 'ROOM', 'COURTYARD'], default: 'ROOM' }
})
Worker
const workerSchema = new mongoose.Schema({
name: { type: String, required: true },
workGroup: { type: Schema.Types.ObjectId, ref: 'WorkGroup', required: false }
})
I have built my query like this:
WorkerLocationContext.aggregate([
{
"$lookup": {
"from": "HeatMeasureContext",
"localField": "sensor.location._id",
"foreignField": "sensor.location._id",
"as": "HMContext"
}
},
{
"$match": {
"$and": [
{ "$or": [
{ "$and": [
{
"HMContext.sensor.placementType": { "$eq": "INTERNAL" }},
{"HMContext.internal": { "$gte": limit}
},
{
"HMContext.sensor.placementType": { "$eq": "EXTERNAL" }},
{"HMContext.external": { "$gte": limit}
},
]},
]},
{ "WorkerLocationContext.worker.location.type": { "$ne": "REST" } }
]
}
},
{
"$group": {
"_id": "null",
"workers": {
"$count": {}
},
"hmDatetime": {
"$max": "$HMContext.createdAt"
},
"wlDatetime": {
"$max": "$WorkerLocationContext.createdAt"
}
}
}
]);
Basically, my goal with it is to count how many workers fit in that condition according to their current location, thus the latest registers in the context tables. I have tried some simulations in the mongoplayground, but nothing succeeded. Is it possible to be done in MongoDB? Can you help me?
Thanks in advance!
Edit 1
Sample Data
- Worker
[
{ "_id": "6181de993fca98374cf901f6", "name": "Worker 1", "workGroup": "6181de3e3fca98374cf901f4", "__v": 0 },
{ "_id": "6181dec33fca98374cf901f7", "name": "Worker 2", "workGroup": "6181de4a3fca98374cf901f5", "__v": 0 },
{ "_id": "6181decc3fca98374cf901f8", "name": "Worker 3", "workGroup": "6181de4a3fca98374cf901f5", "__v": 0 },
{ "_id": "6181ded13fca98374cf901f9", "name": "Worker 4", "workGroup": "6181de4a3fca98374cf901f5", "__v": 0 }
]
- Location
[
{ "_id": "6181df293fca98374cf901fa", "name": "Location 1", "description": "Rest place", "__v": 0, "type": "ROOM" },
{ "_id": "6181df3b3fca98374cf901fb", "name": "Location 2", "description": "Room 1", "__v": 0, "type": "ROOM" }
]
- MeasureSensor
[
{ "_id": "6181e5ae3fca98374cf901fc", "name": "Sensor 1", "description": "Heat Sensor 1", "location": "6181df3b3fca98374cf901fb", "measurerType": "HEAT", "__v": 0, "placementType": "INTERNAL", "sensorType": "ENVIRONMENT", "type": "MEASURE" }
]
- LocationSensor
[
{ "_id": "6181e5f83fca98374cf901fd", "name": "Location Sensor 1", "description": "Location sensor for Location 2", "location": "6181df3b3fca98374cf901fb", "trackerType": "RFID", "__v": 0, "sensorType": "ENVIRONMENT", "type": "LOCATION" }
]
- WorkerLocationContext
[
{ "_id": "615676c885ccad55a493503b", "updatedAt": "2021-10-01T02:47:36.207Z", "createdAt": "2021-10-01T02:47:36.207Z", "sensor": "615657572079a55f7814947b", "worker": "6153dcfb58ad722c747eb42d", "__v": 0 },
{ "_id": "618311b56b77f445ecf73277", "updatedAt": "2021-11-03T22:48:21.887Z", "createdAt": "2021-11-03T22:48:21.887Z", "sensor": "6181e5f83fca98374cf901fd", "worker": "6181de993fca98374cf901f6", "__v": 0 },
{ "_id": "618311c86b77f445ecf73278", "updatedAt": "2021-11-03T22:48:40.507Z", "createdAt": "2021-11-03T22:48:40.507Z", "sensor": "6181e5f83fca98374cf901fd", "worker": "6181decc3fca98374cf901f8", "__v": 0 }
]
- HeatMeasureContext
[
{ "_id": "61831b796b77f445ecf7327b", "updatedAt": "2021-11-03T23:30:01.640Z", "createdAt": "2021-11-03T23:30:01.640Z", "sensor": "6181e5ae3fca98374cf901fc", "mercury": 25.8, "humid": 23.5, "globe": 25.5, "external": 24.13, "internal": 24.1, "__v": 0 },
{ "_id": "61831bc96b77f445ecf7327c", "updatedAt": "2021-11-03T23:31:21.080Z", "createdAt": "2021-11-03T23:31:21.080Z", "sensor": "6181e5ae3fca98374cf901fc", "mercury": 28.6, "humid": 27.8, "globe": 27, "external": 27.72, "internal": 27.56, "__v": 0 }
]
Edit 2
I had to simplify a bit my query because some expressions like heatMeasureContex.sensor.location wouldn't work in there (as far as I know), but here is a simple trial that is not working, and isn't even the half of what I need: mongopplaygroung.net
You can start an aggregation pipeline from the HeatMeasureContext collection:
$match on the internal or external field
$lookup the WorkerLocationContext collection using an sub-pipeline. In the sub-pipeline, $sum the worker count and get the $max wlDatetime
$unwind the result for further processing
$group again on HeatMeasureContext.location, use $first to get the result in sub-pipeline and $max to get the hmDatetime
db.HeatMeasureContext.aggregate([
{
$match: {
$expr: {
$or: [
{
$gte: [
"$internal",
27
]
},
{
$gte: [
"$external",
27
]
}
]
}
}
},
{
"$lookup": {
"from": "WorkerLocationContext",
let: {
loc: "$location"
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$$loc",
"$location"
]
}
}
},
{
$group: {
_id: "$location",
"workers": {
"$sum": 1
},
"wlDatetime": {
"$max": "$createdAt"
}
}
}
],
"as": "workerAggResult"
}
},
{
$unwind: "$workerAggResult"
},
{
$group: {
_id: "$location",
"hmDatetime": {
$max: "$createdAt"
},
"wlDatetime": {
$first: "$workerAggResult.wlDatetime"
},
"workers": {
$first: "$workerAggResult.workers"
}
}
}
])
Here is the Mongo playground for your reference.
Well, after some studying and going through the MongoDB University Aggregation Framework course (which I found out to be very good, I highly recommend), I was able to figure how to do what I needed:
db.heatmeasurecontexts.aggregate([
{
'$group': {
'_id': '$sensor',
'createdAt': {
'$last': '$createdAt'
},
'external': {
'$last': '$external'
},
'internal': {
'$last': '$internal'
}
}
}, {
'$lookup': {
'from': 'measuresensors',
'localField': '_id',
'foreignField': '_id',
'as': 'sensor'
}
}, {
'$unwind': {
'path': '$sensor'
}
}, {
'$match': {
'$or': [
{
'$and': [
{
'sensor.placementType': {
'$eq': 'INTERNAL'
}
}, {
'internal': {
'$gte': 27
}
}
]
}, {
'$and': [
{
'sensor.placementType': {
'$eq': 'EXTERNAL'
}
}, {
'external': {
'$gte': 25
}
}
]
}
]
}
}, {
'$project': {
'_id': 0,
'measure_sensor_location': '$sensor.location'
}
}, {
'$lookup': {
'from': 'locationsensors',
'localField': 'measure_sensor_location',
'foreignField': 'location',
'as': 'location_sensor'
}
}, {
'$unwind': {
'path': '$location_sensor'
}
}, {
'$lookup': {
'from': 'workerlocationcontexts',
'localField': 'location_sensor._id',
'foreignField': 'sensor',
'as': 'worker_location_context'
}
}, {
'$unwind': {
'path': '$worker_location_context'
}
}, {
'$project': {
'worker_location_context': 1,
'location_sensor': 1
}
}, {
'$lookup': {
'from': 'workers',
'localField': 'worker_location_context.worker',
'foreignField': '_id',
'as': 'worker_location_context.worker'
}
}, {
'$unwind': {
'path': '$worker_location_context.worker'
}
}, {
'$match': {
'$expr': {
'$eq': [
'$location_sensor.location', '$worker_location_context.worker.currentLocation'
]
}
}
}, {
'$group': {
'_id': {
'sensor': '$worker_location_context.sensor',
'sensor_location': '$location_sensor.location',
'worker': '$worker_location_context.worker._id',
'worker_location': '$worker_location_context.worker.currentLocation'
},
'createdAt': {
'$last': '$worker_location_context.createdAt'
}
}
}, {
'$count': 'workers_at_risk'
}
])
I hope it may be useful eventually, despite the fact that this is a very specific scenario.

How to query to get all documents referenced to another collection based on one field as username

In my Node API and MongoDB, I'm trying to make an endpoint to get all the posts associated with one username of a profile. In my Profile schema, I have a reference to the Post Schema and in my Post schema, I have a reference to the Username from Profile schema.
My issue I don't know how to get all the posts for that username. I did similarly but with embedded for the Experience schema but I'm not sure how to do that for the referenced collections.
Post model:
const { Connect } = require("../db");
const reactionSchema = {
likedBy: {
type: String,
unique: true,
sparse: true
}
};
const postSchema = {
text: {
type: String,
required: true,
unique: true,
sparse: false
},
username: {
type: Connect.Schema.Types.String,
ref: "Profile"
},
image: {
type: String,
default: "https://via.placeholder.com/150",
required: false
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
reactions: [reactionSchema],
comments: {
type: Connect.Schema.Types.ObjectId,
ref: "Comment",
required: false
}
};
const collectionName = "post";
const postSchemaModel = Connect.Schema(postSchema);
const Post = Connect.model(collectionName, postSchemaModel);
module.exports = Post;
Profile model:
// Here defining profile model
// Embedded we have the Experience as []
const { Connect } = require("../db");
const { isEmail } = require("validator");
const postSchema = {
type: Connect.Schema.Types.ObjectId,
ref: "Post"
};
const experienceSchema = {
role: {
type: String,
required: true
},
company: {
type: String,
required: true
},
startDate: {
type: Date,
required: true
},
endDate: {
type: Date,
required: false
},
description: {
type: String,
required: false
},
area: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
username: {
type: String,
required: false
},
image: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
}
};
const profileSchema = {
firstname: {
type: String,
required: true
},
surname: {
type: String,
required: true
},
email: {
type: String,
trim: true,
lowercase: true,
unique: true,
required: [true, "Email is required"],
validate: {
validator: string => isEmail(string),
message: "Provided email is invalid"
}
},
bio: {
type: String,
required: true
},
title: {
type: String,
required: true
},
area: {
type: String,
required: true
},
imageUrl: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
},
username: {
type: String,
required: true,
unique: true
},
experience: [experienceSchema],
posts: [postSchema],
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
}
};
const collectionName = "profile";
const profileSchemaModel = Connect.Schema(profileSchema);
const Profile = Connect.model(collectionName, profileSchemaModel);
module.exports = Profile;
I was able to make this for the embedded experience but not sure that correct for referenced collection:
const profileWithExperiences = await Student.aggregate([
{ $match: { username: res.username.username } },
{
$unwind: "$experience"
},
{
$match: {
"experience._id": new ObjectID(req.params.experienceId)
}
},
{
$project: {
username: 1,
experience: 1,
_id: 0
}
}
]);
I would like to see an example for referenced collections as it is confusing me how should I do that
[EDIT]
JSON for Profiles and Posts
{
"_id": ObjectId("5e2c98fc3d785252ce5b5693"),
"imageUrl": "https://i.pravatar.cc/300",
"firstname": "Jakos",
"surname": "Lemi",
"email": "lemi#email.com",
"bio": "My bio bio",
"title": "Senior IT developer",
"area": "Copenhagen",
"username": "Jakos",
"experience": [
{
"image": "https://via.placeholder.com/150",
"_id": ObjectId("5e3975f95fbeec9095ff3d2f"),
"role": "Developer",
"company": "Google",
"startDate": ISODate("2018-11-09T23:00:00.000Z"),
"endDate": ISODate("2019-01-05T23:00:00.000Z"),
"area": "Copenhagen",
"createdAt": ISODate("2020-02-04T13:47:37.167Z"),
"updatedAt": ISODate("2020-02-04T13:47:37.167Z")
},
{
"image": "https://via.placeholder.com/150",
"_id": ObjectId("5e3978bf5e399698e20c56d4"),
"role": "Developer",
"company": "IBM",
"startDate": ISODate("2018-11-09T23:00:00.000Z"),
"endDate": ISODate("2019-01-05T23:00:00.000Z"),
"area": "Copenhagen",
"createdAt": ISODate("2020-02-04T13:59:27.412Z"),
"updatedAt": ISODate("2020-02-04T13:59:27.412Z")
}
],
"createdAt": ISODate("2020-01-25T19:37:32.727Z"),
"updatedAt": ISODate("2020-02-04T23:14:37.122Z"),
"__v": NumberInt("0")
}
Post
{
"_id": ObjectId("5e3beb639e072afedd19dcef"),
"username": ObjectId("5e2c98fc3d785252ce5b5693"),
"image": "https://via.placeholder.com/150",
"text": "My awesome post",
"createdAt": ISODate("2020-02-06T10:33:07.22Z"),
"updatedAt": ISODate("2020-02-06T10:33:07.22Z"),
"reactions": [ ],
"__v": NumberInt("0")
}
Output expected:
{
"username": "Jakos",
"postsCount": [1],
"posts": [
{
"_id": ObjectId("5e3beb639e072afedd19dcef"),
"image": "https://via.placeholder.com/150",
"text": "My awesome post",
"createdAt": ISODate("2020-02-06T10:33:07.22Z"),
"updatedAt": ISODate("2020-02-06T10:33:07.22Z"),
"reactions": [ ],
"__v": NumberInt("0")
}
]
}
I want to see all the posts related to that username
You can use the $lookup aggregation to join collections.
db.profiles.aggregate([
{
$match: {
username: "Jakos"
}
},
{
$lookup: {
from: "posts", //the name of the posts collection, change this if it is different
localField: "_id",
foreignField: "username",
as: "posts"
}
},
{
$project: {
username: 1,
posts: 1,
postsCount: {
$size: "$posts"
},
_id: 0
}
}
])
Playground
For mongoose it should be like this in your app:
const profileWithExperiences = await Student.aggregate([
{ $match: { username: res.username.username } },
{
$unwind: "$experience"
},
{
$lookup: {
from: "posts", //the name of the posts collection, change this if it is different
localField: "_id",
foreignField: "username",
as: "posts"
}
},
{
$project: {
username: 1,
posts: 1,
postsCount: {
$size: "$posts"
},
_id: 0
}
}
]);
Try to get like this i am getting data from two table with the use of node and mongodb.
var param = {};
param['user_id']=id;
var search={ user_id:param.user_id,status: [ 'Pending', 'Accepted' ] };
var output={};
output = await JobRequest.find(search);
if(output !=0)
{
var JSon=await JobRequest.aggregate([
{$match: { user_id: {$gte:id}} },
{
"$project": {
"employee_id": {
"$toObjectId": "$employee_id"
},
"service_id": {
"$toObjectId": "$service_id"
},
"createdDate": {
"$toString": "$createdDate"
},
"chat_status": {
"$toString": "$chat_status"
},
"status": {
"$toString": "$status"
},
"delivery_address": {
"$toString": "$delivery_address"
},
"delivery_lat": {
"$toString": "$delivery_lat"
},
"delivery_lang": {
"$toString": "$delivery_lang"
},
}
},
{
$lookup:
{
from: "employees",
localField: "employee_id",
foreignField: "_id",
as: "employee_details"
}
},
{
$lookup:
{
from: "services",
localField: "service_id",
foreignField: "_id",
as: "service_details"
}
}
]);

Check follow status in aggregate mongo / mongoose

I have this schema for users where followers/followed is array and the reference the same schema
var userSchema = new Schema({
username: { type: String, unique: true, trim: true, required: true },
password: { type: String, required: true },
followers: [{ type: Schema.Types.ObjectId, ref: "users" }],
followed: [{ type: Schema.Types.ObjectId, ref: "users" }],
registered: { type: Date, default: Date.now },
admin: { type: Number, default: 0 }
});
What I am looking for to return the follow status, if the _id is contains in followed array give me for example follow_status: 1
[
{
$match: { username: new RegExp(username, "i") }
},
{
$unwind: "$followers"
},
{
$lookup: {
from: "users",
localField: "followers",
foreignField: "_id",
as: "info"
}
},
{
$unwind: "$info"
},
{
$project: {
info: {
_id: 1,
username: 1,
avatar: { $ifNull: ["$avatar", ""] },
fullname: { $ifNull: ["$fullname", ""] }
}
}
},
{
$replaceRoot: { newRoot: "$info" }
},
{
$limit: 1000
}
]
Current pipeliens result
[
{
"_id": "5a906653f52e66c9c7a23cb6",
"username": "User1"
},
{
"_id": "5a908eb564a726cf8ec7e0a3",
"username": "User2"
}
]