So i have an document of answers from user with structure like this:
[{
"_id": {
"$oid": "636e685d1e1b4aa82f7e87c7"
},
"userId": {
"$oid": "6369b17b11e02557349d8e37"
},
"formId": {
"$oid": "6361d3bf914c7e5a21efa190"
},
"title": "Order Kerja Produksi (KSNI)",
"username": "22000510",
"date": "2022-11-11",
"createdAt": 1668180061,
"updatedAt": 1668180061,
"__v": 0,
"position": "Foreman",
"department": "Production"
},
{
"_id": {
"$oid": "636e699c1e1b4aa82f7e87cb"
},
"userId": {
"$oid": "6369b17b11e02557349d8e37"
},
"formId": {
"$oid": "6361d3bf914c7e5a21efa190"
},
"title": "Order Kerja Produksi (KSNI)",
"username": "22000510",
"date": "2022-11-11",
"createdAt": 1668180380,
"updatedAt": 1668180380,
"__v": 0,
"department": "Production",
"position": "Foreman"
},
{
"_id": {
"$oid": "636e6ace1e1b4aa82f7e87cf"
},
"userId": {
"$oid": "6369b17b11e02557349d8e37"
},
"formId": {
"$oid": "6361d3bf914c7e5a21efa190"
},
"title": "Order Kerja Produksi (KSNI)",
"username": "22000510",
"date": "2022-11-11",
"createdAt": 1668180686,
"updatedAt": 1668180686,
"__v": 0,
"department": "Production",
"position": "Foreman"
}
]
each NIK has assigned with SPV on the Users document, that have structure like this:
{
"_id": {
"$oid": "6369b17b11e02557349d8de6"
},
"password": "$2b$10$whBbgZRMsIMCgKy/EJAwXefSdZNnrK5b.cSOYXTqu7g5a2uwCddKm",
"NIK": "19000298",
"department": "Production",
"__v": 0,
"createdAt": 1667871099,
"updatedAt": 1667871099,
"plant": "RANC",
"Gedung_Zona": "No Status",
"SPV": "JAMJAM J",
"Sector": "2"
},
{
"_id": {
"$oid": "6369b17b11e02557349d8de7"
},
"password": "$2b$10$whBbgZRMsIMCgKy/EJAwXefSdZNnrK5b.cSOYXTqu7g5a2uwCddKm",
"NIK": "20000100",
"Group_Shift": "R1",
"role": "user",
"__v": 0,
"createdAt": 1667871099,
"updatedAt": 1670974129,
"plant": "RANC",
"Gedung_Zona": "No Status",
"SPV": "JAMJAM J",
"Sector": "3"
},
]
I want to aggregate the answers from answers document with condition from users document where condition like this:
{$match:{SPV:"SPV_name"}}
Is that a possible way to produce it into this kind of response with condition above using $lookup and $group?
If thats possible any help on how to produce that?
any help will be very thankful
Here is what i want the response from the query..
{
_id:1243135421412,
formId:123123123123,
title:"title of the question",
username:22004627,
date:2022-10-10,
createdAt:1234125525,
SPV:"SPV_NAME",
},
{
_id:1243135421412,
formId:123123123123,
title:"title of the question",
username:22004777,
date:2022-10-12,
createdAt:1234125525,
SPV:"SPV_NAME",
}
here is my try but it keeps returning error :
MongoServerError: Expression $arrayElemAt takes exactly 2 arguments. 1 were passed in.
Here is my try:
db.answers.aggregate([{$lookup:{from:"users",pipeline:[{$match:{SPV:"JAMJAM JAMALUDIN"}}],as:"data"}}])
Related
`I have two collections in MongoDB. One is users and the other is companies. I need to be able to populate the users.endpoints with the endpoints from companies that match ObjectID's which are in the user.endPoints property. It is a bit hard for me to wrap my head around considering there are two steps.
This is the companies collection.
{
"_id": {
"$oid": "63ed39162bfc2cf8065b76cf"
{
"_id": {
"$oid": "63ed39162bfc2cf8065b76cf"
},
"companyName": "Sowegatel",
"amount": 0,
"signalwireSid": "id",
"numbers": [
{
"number": "+12068133580",
"_id": {
"$oid": "63ed39c72bfc2cf8065b76f0"
},
"createdAt": {
"$date": {
"$numberLong": "1676491207931"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1676491207931"
}
}
}
],
"endPoints": [
{
"userName": "4009",
"_id": "fb1d0ef9-c713-400e-a3c9-cbc6823aaf57"
},
{
"userName": "4019",
"_id": "506e710d-14a6-4345-bc89-8488af4cabe4"
},
{
"userName": "4020",
"_id": "c80bd1ab-ca8d-4649-9d35-56d64ef8fab5",
"type": "sip_endpoint"
}
],
"__v": 6
} },
"companyName": "Sowegatel",
"amount": 0,
"signalwireSid": "id",
"numbers": [
{
"number": "+12068133580",
"_id": {
"$oid": "63ed39c72bfc2cf8065b76f0"
},
"createdAt": {
"$date": {
"$numberLong": "1676491207931"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1676491207931"
}
}
}
],
"endPoints": [
{
"userName": "4009",
"_id": "fb1d0ef9-c713-400e-a3c9-cbc6823aaf57"
},
{
"userName": "4019",
"_id": "506e710d-14a6-4345-bc89-8488af4cabe4"
},
{
"userName": "4020",
"_id": "c80bd1ab-ca8d-4649-9d35-56d64ef8fab5",
"type": "sip_endpoint"
}
],
"__v": 6
}
This is the users collection.
{
"_id": {
"$oid": "63ed39162bfc2cf8065b76d2"
},
"firstName": "mark",
"lastName": "thomas",
"email": "mt#st.com",
"password": "",
"companyId": {
"$oid": "63ed39162bfc2cf8065b76cf"
},
"active": true,
"role": "companyAdmin",
"tokens": [],
"__v": 2,
"endpoints": [
// I need to populate to endpoints here!!!! //
"c80bd1ab-ca8d-4649-9d35-56d64ef8fab5"
]
}
I can do a single step aggregation, but this is a little complicated for me.`
Node js using mongoose as ORM. I have set of documents like below
I want to calculate the average time for createdAt in ISO String(format) field in duration of hours on
grouping the category field. I have tried many ways to use aggregate but couldn't get the result.
[{
"_id": {
"$oid": "62dfc2cf25735e8b1b475ff1"
},
"numLikes": 0,
"numViews": 0,
"numShares": 0,
"hasUserLiked": false,
"title": "sample-broadcast",
"description": "broadcast-dewscription",
"projectId": {
"$oid": "62d903a5dade1714382b27af"
},
"content": [
{
"_id": {
"$oid": "62dfc2cf25735ee18d475ff2"
},
"downloadLink": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/51daead4-1134-4921-a544-fea845f03d1c/uploadbroadcast/1658831544",
"label": "lance-anderson-QdAAasrZhdk-unsplash (1).jpg",
"contentType": "jpeg"
}
],
"delivery": "scheduleBroadcast",
"category": "GENERAL_UPDATES",
"groupId": "51daead4-1134-4921-a544-fea845f03d1c",
"author": {
"userId": "83314517-9326-430f-9c4e-8fedb050e6b0",
"profilePic": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/4f670832-dfd7-43ee-a6ad-e2f43f48df6a/uploadprofilepic/1658239806",
"name": "Biswajit Rout"
},
"projectLogo": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/4f670832-dfd7-43ee-a6ad-e2f43f48df6a/uploadcompanylogo%2A/1658239764",
"createdAt": {
"$date": {
"$numberLong": "1658831567577"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1658831567577"
}
},
"__v": 0
},{
"_id": {
"$oid": "62dfebae25735e015f476dfb"
},
"numLikes": 0,
"numViews": 0,
"numShares": 0,
"hasUserLiked": false,
"title": "testing-broadcast",
"description": "testing-description",
"projectId": {
"$oid": "62d903a5dade1714382b27af"
},
"content": [
{
"_id": {
"$oid": "62dfebae25735e291c476dfc"
},
"downloadLink": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/51daead4-1134-4921-a544-fea845f03d1c/projectimages0/1658842001",
"label": "lance-anderson-QdAAasrZhdk-unsplash (1).jpg",
"contentType": "jpeg"
},
{
"_id": {
"$oid": "62dfebae25735e0321476dfd"
},
"downloadLink": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/51daead4-1134-4921-a544-fea845f03d1c/projectimages1/1658842024",
"label": "Get_Started_With_Smallpdf.pdf",
"contentType": "pdf"
}
],
"delivery": "immediate",
"link": "http://localhost:3000",
"category": "GENERAL_UPDATES",
"groupId": "51daead4-1134-4921-a544-fea845f03d1c",
"author": {
"userId": "83314517-9326-430f-9c4e-8fedb050e6b0",
"profilePic": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/4f670832-dfd7-43ee-a6ad-e2f43f48df6a/uploadprofilepic/1658239806",
"name": "Biswajit Rout"
},
"projectLogo": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/4f670832-dfd7-43ee-a6ad-e2f43f48df6a/uploadcompanylogo%2A/1658239764",
"createdAt": {
"$date": {
"$numberLong": "1658842030827"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1658842030827"
}
},
"__v": 0
},{
"_id": {
"$oid": "62e144677fc76b0373f40152"
},
"numLikes": 0,
"numViews": 0,
"numShares": 0,
"hasUserLiked": false,
"title": "Broker Offer-1",
"description": "50% off on the membership for early birds. \n\nOffer Applied to first fifty users only",
"projectId": {
"$oid": "62d903a5dade1714382b27af"
},
"content": [
{
"_id": {
"$oid": "62e144677fc76b2b79f40153"
},
"downloadLink": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/51daead4-1134-4921-a544-fea845f03d1c/projectimages0/1658930275",
"label": "50-off-PNG-Picture.png",
"contentType": "png"
}
],
"delivery": "immediate",
"link": "",
"category": "OFFER_BROKERS",
"groupId": "51daead4-1134-4921-a544-fea845f03d1c",
"author": {
"userId": "83314517-9326-430f-9c4e-8fedb050e6b0",
"profilePic": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/4f670832-dfd7-43ee-a6ad-e2f43f48df6a/uploadprofilepic/1658239806",
"name": "Biswajit Rout"
},
"projectLogo": "https://builder-broadcast-media.s3.ap-south-1.amazonaws.com/builder-broadcast-media/4f670832-dfd7-43ee-a6ad-e2f43f48df6a/uploadcompanylogo%2A/1658239764",
"createdAt": {
"$date": {
"$numberLong": "1658930279871"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1658930279871"
}
},
"__v": 0
}]
My expected result should be like this
{
OFFER_BROKERS: 5 <hrs>,
GENERAL_UPDATES : 4 <hrs>
}
Do you want to convert milliseconds to real time and give it to orm
I want to join more than two collections in MongoDB . Is it possible to join?
I have 2 collections and I want to join them based by their ids
news collection
{
"lang": "ru",
"news": [{
"title": "title",
"content": "desc",
"image": "path",
"categoryId": {
"$oid": "6171499e0ba3d75082823c9a"
},
"createdAt": {
"$date": "2021-10-21T12:30:33.215Z"
},
"_id": {
"$oid": "61715d7990905adefcf314d1"
}
}]
}
and I have got newscategory collection like that
[
{
"lang": "ru",
"categories": [{
"name": "sdfsdsdcsdf",
"_id": {
"$oid": "6171499e0ba3d75082823c9a"
}
}]
},
{
"lang": "en",
"categories": [{
"name": "ooo",
"_id": {
"$oid": "61712980f8ee795c6a569dcb"
}
}, {
"name": "yuy",
"_id": {
"$oid": "61712980f8ee795c6a569dcc"
}
}, {
"name": "rtyrty",
"_id": {
"$oid": "61712980f8ee795c6a569dcd"
}
}]
}
]
Expected Output:
[
{
"_id": "61715d7990905adefcf314d0",
"lang": "ru",
"news": [
{
"title": "sdf",
"content": "sdf",
"image": "asdas",
"categoryId": "6171499e0ba3d75082823c9a",
"caregory": [
{
"name": "sdfsdsdcsdf",
"_id": "6171499e0ba3d75082823c9a"
},
]
"createdAt": "2021-10-21T12:30:33.215Z",
"_id": "61715d7990905adefcf314d1"
}
],
Match is based on both "category_id" and "categories._id".
How can I achieve result like that ?
I need to filter some users according to some fixed criteria. I have a user collection and a talent collection. The talent collection holds the reference to a master category collection.
What I need is to filter these users according to the category in the talent collection and some keys from the user collection.
For example I need to search for a user whose gender is 'male' and education 'BTech' and will have talents as a programmer and tester
my user collection is like,
{
"_id": "5f1939239bd35429ac9cd78f",
"isOtpVerified": "false",
"role": "user",
"adminApproved": 1,
"status": 0,
"languages": "Malayalam, Tamil, Telugu, Kannada",
"name": "Test user",
"email": "test#email.com",
"phone": "1234567890",
"otp": "480623",
"uid": 100015,
"bio": "Short description from user",
"dob": "1951-09-07T00:00:00.000Z",
"gender": "Male",
"education": "Btech",
"bodyType": "",
"complexion": "",
"height": "",
"weight": "",
"requests": [],
"location": {
"place": "place",
"state": "state",
"country": "country"
},
"image": {
"avatar": "5f1939239bd35429ac9cd78f_avatar.jpeg",
"fullsize": "5f1939239bd35429ac9cd78f_fullsize.png",
"head_shot": "5f1939239bd35429ac9cd78f_head_shot.jpeg",
"left_profile": "5f1939239bd35429ac9cd78f_left_profile.png",
"right_profile": "5f1939239bd35429ac9cd78f_right_profile.png"
},
"__v": 42,
"createdAt": "2020-07-23T07:15:47.387Z",
"updatedAt": "2020-08-18T18:54:22.272Z",
}
Talent collection
[
{
"_id": "5f38efef179aca47a0089667",
"userId": "5f1939239bd35429ac9cd78f",
"level": "5",
"chars": {
"type": "Fresher",
},
"category": "5f19357b50bcf9158c6be572",
"media": [],
"createdAt": "2020-08-16T08:35:59.692Z",
"updatedAt": "2020-08-16T08:35:59.692Z",
"__v": 0
},
{
"_id": "5f3b7e6f7e322948ace30a2c",
"userId": "5f1939239bd35429ac9cd78f",
"level": "3",
"chars": {
"type": "Fresher",
},
"category": "5f19359250bcf9158c6be573",
"media": [
{
"adminApproved": 0,
"status": 0,
"_id": "5f3c22573065f84a48e04a14",
"file": "id=5f1939239bd35429ac9cd78f&dir=test&img=5f1939239bd35429ac9cd78f_image_undefined.jpeg",
"description": "test",
"fileType": "image",
"caption": "test file"
},
{
"adminApproved": 0,
"status": 0,
"_id": "5f3c2d7a8c7f8336b0bfced2",
"file": "id=5f1939239bd35429ac9cd78f&dir=test&img=5f1939239bd35429ac9cd78f_image_1.jpeg",
"description": "this is a demo poster for testing",
"fileType": "image",
"caption": "A Test Poster"
}
],
"createdAt": "2020-08-18T07:08:31.532Z",
"updatedAt": "2020-08-18T19:35:22.899Z",
"__v": 2
}
]
And the category in the above document is a separate one populated to this. the category collection as,
[
{
"_id": "5f19359250bcf9158c6be573",
"status": true,
"title": "Testing",
"description": "Application tester",
"code": "test",
"characteristics": [],
"createdAt": "2020-07-23T07:00:34.221Z",
"updatedAt": "2020-07-23T07:00:34.221Z",
"__v": 0
},
{
"status": true,
"_id": "5f29829a705b4e648c28bc88",
"title": "Designer",
"description": "UI UX Designer",
"code": "uiux",
"createdAt": "2020-08-04T15:45:30.125Z",
"updatedAt": "2020-08-04T15:45:30.125Z",
"__v": 0
},
{
"_id": "5f19357b50bcf9158c6be572",
"status": true,
"title": "programming",
"description": "Java programmer",
"code": "program",
"createdAt": "2020-07-23T07:00:11.137Z",
"updatedAt": "2020-07-23T07:00:11.137Z",
"__v": 0
}
]
So my filter terms will be;
{
categories: ["5f19359250bcf9158c6be573", "5f19357b50bcf9158c6be572"],
minAge: 18,
maxAge: 25,
minHeight: 5,
maxHeight: 6,
minWeight: 50,
maxWeight: 80,
complexion: "white",
gender: "male",
}
And the expected result will be a user have both the above talents and followed conditions,
{
users: { ..User details.. },
medias: { ...medias from the matching talents.. }
}
If there are two collections you need to join them either by primary key or _id with foriegn fields and you can use $lookup with $match to filter down.
Documentation
You need to use $lookup with pipeline,
$match you condition for category match
$lookup to join users collection
$match conditions for users collections fields
$match exclude documents that don't found matching users of criteria passed in conditions
db.talents.aggregate([
{
$match: {
category: { $in: ["5f19359250bcf9158c6be573", "5f19357b50bcf9158c6be572"] }
}
},
{
$lookup: {
from: "users",
as: "users",
let: { userId: "$userId" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ["$$userId", "$_id"] },
{ $eq: ["$gender", "Male"] },
{ $eq: ["$education", "Btech"] }
// ... add you other match criteria here
]
}
}
}
]
}
},
{ $match: { users: { $ne: [] } } }
])
Playground
I need to get a list of item using the mongoose, however, i need select only one item of any type (i've 5 possible values), and always the last inserted item of this type.
for example, to the list below, not ordered (i know, here it's ordered).
[
{
"_id": "5b226abab64b2309de01bfd5",
"documentType": "type3",
"createdAt": "2018-06-14T13:16:42.321Z"
},
{
"_id": "5b226a5da93b0e09b8aee447",
"documentType": "type3",
"createdAt": "2018-06-14T13:15:09.458Z"
},
{
"_id": "5b226a21f454d6097ffa461c",
"documentType": "type2",
"createdAt": "2018-06-14T13:14:09.159Z"
},
{
"_id": "5b2267fb445d7709590e1695",
"documentType": "type1",
"createdAt": "2018-06-14T13:04:59.742Z"
},
{
"_id": "5b2267de76708b094696b0fe",
"documentType": "type3",
"createdAt": "2018-06-14T13:04:30.349Z"
},
{
"_id": "5b2267ce2f3724092b1a14a3",
"documentType": "type2",
"createdAt": "2018-06-14T13:04:14.410Z"
},
{
"_id": "5b2267a92f3724092b1a14a2",
"documentType": "type4",
"createdAt": "2018-06-14T13:03:37.079Z"
},
{
"_id": "5b22647b63017e08a69a3043",
"documentType": "type5",
"createdAt": "2018-06-14T12:50:03.999Z"
},
{
"_id": "5b2264471778a20880d4ba64",
"documentType": "type5",
"createdAt": "2018-06-14T12:49:11.773Z"
}
]
the expected result is something like this:
[
{
"_id": "5b226abab64b2309de01bfd5",
"documentType": "type3",
"createdAt": "2018-06-14T13:16:42.321Z"
},
{
"_id": "5b226a21f454d6097ffa461c",
"documentType": "type2",
"createdAt": "2018-06-14T13:14:09.159Z"
},
{
"_id": "5b2267fb445d7709590e1695",
"documentType": "type1",
"createdAt": "2018-06-14T13:04:59.742Z"
},
{
"_id": "5b2267a92f3724092b1a14a2",
"documentType": "type4",
"createdAt": "2018-06-14T13:03:37.079Z"
},
{
"_id": "5b22647b63017e08a69a3043",
"documentType": "type5",
"createdAt": "2018-06-14T12:50:03.999Z"
}
]
Basicly only one per type, sort desc by id
How can i do this?
You can use $group by in mongodb to distinct the documentType
db.collection.aggregate([
{ "$group": {
"_id": "$documentType",
"createdAt": { "$first": "$createdAt" },
"id": { "$first": "$_id" }
}},
{ "$project": {
"_id": "$id",
"createdAt": 1,
"documentType": "$_id"
}}
])
The output will be
[
{
"_id": "5b226abab64b2309de01bfd5",
"createdAt": "2018-06-14T13:16:42.321Z",
"documentType": "type3"
},
{
"_id": "5b2267fb445d7709590e1695",
"createdAt": "2018-06-14T13:04:59.742Z",
"documentType": "type1"
},
{
"_id": "5b22647b63017e08a69a3043",
"createdAt": "2018-06-14T12:50:03.999Z",
"documentType": "type5"
},
{
"_id": "5b2267a92f3724092b1a14a2",
"createdAt": "2018-06-14T13:03:37.079Z",
"documentType": "type4"
},
{
"_id": "5b226a21f454d6097ffa461c",
"createdAt": "2018-06-14T13:14:09.159Z",
"documentType": "type2"
}
]