convert to asc order of array data using MongoDB - node.js

how to make this data to asc order by user's first name and user's last name.
I got the response, want to sort the records by user's first name but it is taking from creation date I guess when using sort how can I make it base on user's first name and user's last name please guide
{
"response": {
"items": [
{
"_id": "5e71f86bd300b313df52fb2f",
"last_message": {
"text": "Alex",
"users": [
{
"_id": "5e4a8d2d3952132a08ae5764",
"first_name": "zack",
"last_name": "Write"
}
]
},
"texter": [
"alex",
"$0ctg"
],
"title": "New group1",
"group": true,
"members": [
{
"_id": "5e4a8afc3952132a08ae575e",
"first_name": "test3",
"last_name": "test4"
}
],
"managers": [
"5e4a8afc3952132a08ae575e"
],
"member": {
"_id": "5e4a8afc3952132a08ae575e",
"first_name": "test3",
"last_name": "test4"
}
},
{
"_id": "5e4e740f380054797d9db621",
"last_message": {
"text": "",
"users": [
{
"_id": "5e4a8d2d3952132a08ae5764",
"first_name": "yuhan",
"last_name": "jacob"
}
]
},
"texter": [
"",
"",
"",
"",
"",
"new iphone x\n brand new iphone wv wwvqzwzvq had sqswgscq wow you wholeheartedly q \n $600.00",
"helo",
"hello",
"hi"
],
"members": [
{
"_id": "5e4d0973babf2b74ca868f4d",
"first_name": "alex",
"last_name": "hales"
}
],
"managers": [],
"member": {
"_id": "5e4d0973babf2b74ca868f4d",
"first_name": "alex",
"last_name": "hales"
}
}
]
}
}
Tried
{
$sort: {
users: 1,
}
},
doesn't help much
Also if I would like to add two field asc desc order what would be the process in MongoDB

Try this hope this will help you !
{
$sort: { "users.first_name": 1 }
},

Related

How to find data based on sub-field name in MongoDB using Mongoose?

There is a sub-field called 'name' in MongoDB Collection (User):
[
{
"teacher": {
"name": "Alex",
"email": "alex#domain.com"
},
"waiter": {
"name": "Feliks",
"email": "feliks#domain.com"
},
"pilot": [
{
"name": "Sam",
"email": "sam#domain.com"
},
{
"name": "alice",
"email": "alice#domain.com"
}
],
},
{
"teacher": {
"name": "max",
"email": "max#domain.com"
},
"waiter": {
"name": "Sam",
"email": "sam#domain.com"
},
"pilot": [
{
"name": "richard",
"email": "richard#domain.com"
},
{
"name": "alice",
"email": "alice#domain.com"
}
],
}
]
How can I find data based on the field 'name'. For example, when I'm looking for 'Sam', it should return me the all documents since 'Sam' is in "waiter" and "pilot" in first and second documents respectively.
I cannot do something like:
User.find({"teacher.name": "Sam", "waiter.name": "Sam", "pilot.name": "Sam" })
This will return me nothing as it is an AND logic. What I need is an OR logic.
You can use the $or operator.
So the query should look like this:
User.find({ $or: [
{ "teacher.name": "Sam" },
{ "waiter.name": "Sam" },
{ "pilot.name": "Sam" }
]
});
Read here for me details.

Nodejs mongoose : how to retreive data from db collection related to other collection

I want to implement a function that would process students, courses and instructors data (loaded from MongoDB collections) in order to produce information about students enrolled on courses (and store it in another MongoDB collection). the function reports each student’s:
primary key
their name
the number of courses they are enrolled in
I want to Store the output of this routine in a MongoDB collection called coursereport like this :
[
{
"_id": "jeff",
"value": {
"name": "Jeff Holland",
"numbercourses": 2
}
},
{
"_id": "john.shore",
"value": {
"name": "John Shore",
"numbercourses": 2
}
},
{
"_id": "lee2331",
"value": {
"name": "Lee Aldwell",
"numbercourses": 1
}
},
{
"_id": "rcotter",
"value": {
"name": "Ray Cotter",
"numbercourses": 2
}
},
{
"_id": "scott",
"value": {
"name": "Scott Mills",
"numbercourses": 3
}
}
]
my data :
{
"students": [
{
"_id": "john.shore",
"name": {"first": "John", "last": "Shore"},
"email": "john.shore#gmail.com",
"major": "Electrical Engineering"
},
{
"_id": "jeff",
"name": {"first": "Jeff", "last": "Holland"},
"email": "jeff#yahoo.com",
"major": "Business"
},
{
"_id": "scott",
"name": {"first": "Scott", "last": "Mills"},
"email": "scott#hotmail.com",
"major": "Humanities/Art"
},
{
"_id": "rcotter",
"name": {"first": "Ray", "last": "Cotter"},
"email": "rcotter#msn.com",
"major": "Computer Science"
},
{
"_id": "lee2331",
"name": {"first": "Lee", "last": "Aldwell"},
"email": "lee2331#aol.com",
"major": "Graphic Design"
}
],
"courses": [
{
"_id": "HIST-1010",
"name": "History of the World 1010",
"description": "A bunch of really interesting things that actually happened",
"students": ["scott", "john.shore"],
"ratings": [3, 5, 4, 5, 4, 4, 2, 4]
},
{
"_id": "ENGCOMP-1010",
"name": "English Composition 1010",
"description": "If you can't write well, you've got nothing!",
"students": ["scott", "lee2331", "rcotter", "john.shore", "jeff"],
"ratings": [4, 4, 5, 4, 5, 1, 5]
},
{
"_id": "ART-1050",
"name": "Artistic Interpretation 1050",
"description": "Discover your inner beholder",
"students": ["rcotter", "scott", "jeff"],
"ratings": [3, 4, 3, 4, 4, 3, 4, 4]
}
],
"instructors": [
{
"_id": "wally.r.binns",
"name": {"first": "Wally", "middle": "r", "last": "Binns"},
"email": "wally.r.binns#ssu.edu",
"bio": "I was born in the middle of my mother's doctoral dissertation on Faraday Cage isolation. I've been an academic ever since...",
"publications": [{
"title": "Inverted Celestial Poetry",
"source": "http://www.pubcentral.com/poetry/inverted-celestial-poetry"
}],
"courses": ["ENGLIT-2500"]
},
{
"_id": "gerald.waterford.iii",
"name": {"first": "Gerald", "last": "Waterford", "suffix": "III"},
"email": "gerald.waterford.iii#ssu.edu",
"bio": "My father's father was a great man. My father, not so much. I am restoring the family honor.",
"publications": [{
"title": "Grow, grow, little Dandelion",
"source": "http://www.hopefulstories.com/my-dandelion"
}, {"title": "The teapot and the spoon", "source": "http://www.dishsoap.com/teapot-spoon"}],
"courses": ["ENGCOMP-1010", "HIST-1010"]
},
{
"_id": "kim.b",
"name": {"prefix": "Mrs.", "first": "Kim", "last": "Binnley"},
"email": "kim.b#ssu.edu",
"bio": "My mother told me 'Don't let those dopes push you around'. My life has been a constant struggle against dopeness ever since. Sigh...",
"publications": [],
"courses": ["ART-1050"]
}
]
}
I started with that :
async function produceReport(db, callback) {
const students = db.collection('students');
const courses = db.collection('courses');
const instructors = db.collection('instructors');
// implement missing code that will create 'coursereport' mongo collection with student courses data
callback();
}
module.exports = produceReport;
can any one give a help please
You have to use $lookup
Defined as:
To perform an equality match between a field from the input documents with a field from the documents of the “joined” collection,
So you have to join students and courses and later the output value with instructors..
Take a look at this query:
db.students.aggregate([
{
$lookup: {
from: "courses",
localField: "item",
foreignField: "email",
as: "students_courses"
}
},
{
"$lookup": {
"from": "instructors",
"localField": "students_courses._id",
"foreignField": "courses",
"as": "students_courses"
}
},
{
"$set": {
"_id": "$_id",
"value": {
"name": {
"$concat": [
"$name.first",
" ",
"$name.last"
]
},
"numbercourses": {
"$size": "$students_courses"
}
}
}
},
{
"$project": {
"_id": 1,
"value": 1
}
}
])
First stage is a joing with two collections with the fields indicated and soterd into a field called students_courses.
Then, another join with the _ids from the students_courses.
With the data then you can create a field named value with the name and count the number of courses in other field.
And $project to show only fields you want.
Check an example here
db.students.aggregate([
{
$lookup: {
from: "courses",
localField: "_id",
foreignField: "students",
as: "students_courses"
}
},
{
$project: {
_id: 1,
value: {
name: {
$concat: [
"$name.first",
" ",
"$name.last"
]
},
numbercourses: {
"$size": "$students_courses"
}
}
}
}
])

How to filter results from collection the $lookup in mongoose

i want to filter the result as the following in mongodb. I use $lookup to populate the result from another collection. Please check my following code
This code below is what i get
{
"_id": "5f3d563122de0730d0f6a754",
"barcode": "1234",
"productname": "Lays Packet",
"brandName": "Lays",
"productSize": "12",
"price": "12",
"quant": "12",
"imageurl": "http://localhost:3000/images/imageurl-1597855281050.jpg",
"remaining": "12",
"creator": "3d943b957fb5db510d824c5cbd6e8f7d",
"__v": 0,
"source": [
{
"_id": "5f3a9bbc325a074240a1a815",
"firstname": "test",
"lastname": "test",
"storename": "test",
"gst": "test",
"phoneNumber": 1,
"email": "1#demo.com",
"address1": "test",
"address2": "test",
"city": "test",
"state": "test",
"country": "test",
"zip": "1",
"password": "1",
"usertype": 3,
"unique_SHOP": "3d943b957fb5db510d824c5cbd6e8f7d",
"__v": 0
}
]
},
How to retrieve only unique_SHOP and zip from source listing.I want result like the one below with one or more fields
{
"_id": "5f3d563122de0730d0f6a754",
"barcode": "1234",
"productname": "Lays Packet",
"brandName": "Lays",
"productSize": "12",
"price": "12",
"quant": "12",
"imageurl": "http://localhost:3000/images/imageurl-1597855281050.jpg",
"remaining": "12",
"creator": "3d943b957fb5db510d824c5cbd6e8f7d",
"__v": 0,
"source": [
{
"zip": "1",
"unique_SHOP": "3d943b957fb5db510d824c5cbd6e8f7d",
}
]
},
The query i use
List.aggregate([
{$match:
{ productname: { $regex: req.params.query,$options: "i" }}
},
{ $lookup:{
from: "suppliers",
localField: "creator",
foreignField: "unique_SHOP",
as: "source"
}
},
])
You can try $lookup with pipeline,
$match condition of creator id
$project to display required fields
{
$lookup: {
from: "suppliers",
as: "source",
let: { creator: "$creator" },
pipeline: [
{
$match: {
$expr: { $eq: ["$$creator", "$_id"] }
}
},
{
$project: {
_id: 0,
zip: 1,
unique_SHOP: 1
}
}
]
}
}
Playground

Flter mongodb database using mongoose nodejs

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

How to change this response to simple array?

{
"success": true,
"message": "Result",
"data": [
{
"Here": [
{
"_id": "5ee97ee7f25d1c1482717bdf",
"email": "test1#test.io",
"profileImages": [],
"username": "test1",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location",
"firstName": "test1",
"lastName": "test1",
}
]
},
{
"Here": [
{
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
],
}
What I am expecting is this
{
"success": true,
"message": "Result",
data: [
{
"_id": "5ee97ee7f25d1c1482717bdf",
"email": "test1#test.io",
"profileImages": [],
"username": "test1",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location",
"firstName": "test1",
"lastName": "test1"},
{
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
Query I am using is for this response is below using aggregation in mongodb, lookup and project which is leading me to the some undesired response
db.collections.aggregate( [
{
$lookup: {
from: 'users',
as: 'Here',
let: {
whoDid: '$whoDid'
},
pipeline: [
{
"$match": { "$expr": { "$eq": ["$_id", "$$whoDid"] } }
},
{
$project: {
_id: 1,
email: 1,
profileImages: 1,
username: 1,
birthday: 1,
phoneNumber: 1,
firstName: 1,
lastName: 1,
fullName: 1,
// age: {$year: "$birthday"}
age: {
$divide: [{ $subtract: [new Date(), "$birthday"] },
(31558464000)]
}
}
}
],
}
},
{
$project:{
Here:1,
_id:0
}
} ,
])
who did table is one of the collection I have where I have stored the user Id and later I am populating the data using lookup
{
"_id" : ObjectId("5ee988eb1aac0022e15dbb7b"),
"whoDid" : ObjectId("5ee97ef2f25d1c1482717be1"),
"toWhomDid" : ObjectId("5ee97ec0f25d1c1482717bdd"),
"modified_at" : ISODate("2020-06-17T03:07:23.217Z"),
"created_at" : ISODate("2020-06-17T03:07:23.217Z"),
"__v" : 0
}
{
"_id" : ObjectId("5ee988eb1aac0022e15dbb7c"),
"whoDid" : ObjectId("5ee97ec0f25d1c1482717bdd"),
"toWhomDid" : ObjectId("5ee97ef2f25d1c1482717be1"),
"modified_at" : ISODate("2020-06-17T03:07:23.220Z"),
"created_at" : ISODate("2020-06-17T03:07:23.220Z"),
"__v" : 0
}
Can anyone suggest me any better option so that I can get a desired respose?
It is possible to use reduce method:
obj.data = obj.data.reduce((a, c) => {
a.push(...c.Here);
return a;
}, [])
An example:
let obj = {
"success": true,
"message": "Result",
"data": [ {
"Here": [ {
"_id": "5ee97ee7f25d1c1482717bdf", "email": "test1#test.io",
"profileImages": [], "username": "test1",
"birthday": "2020-06-11T10:11:32.000Z", "phoneNumber": "+910000000000", "location": "Test Location",
"firstName": "test1", "lastName": "test1",
}
]
},
{
"Here": [ {
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
]
};
obj.data = obj.data.reduce((a, c) => {
a.push(...c.Here);
return a;
}, [])
console.log(obj);
Add these extra steps into your aggregation pipeline:
{
$unwind: "$Here"
},
{
$replaceWith: "$Here"
}
MongoPlayground
Note: You can replace $project: { _id: 1, email: 1, ... to this:
{
$addFields:{
age: {
$divide: [{ $subtract: [new Date(), "$birthday"] },(31558464000)]
}
}
}

Resources