Extracting some fields from an object in mongodb - node.js

I am new to mongoDB and I am unable to figure out how to extract only few fields from an object in a collection.I have a collection named recipe which is as follow:-
[
{
"_id": "b44e864d-de8f-4110-b676-bbee13417b2e",
"title": "Fried Eggs",
"ingredients": [
{
"name": "Eggs",
"amount": "10"
},
{
"name": "Olive Oil",
"amount": "2 tbs"
}
],
"steps": [
"1. Heat the pan",
"2.Add Olive Oil",
"3. Add Eggs",
"4. Saute"
],
"comments": [
{
"_id": "8604e67c-2426-4742-bc91-25ee1c4064b5",
"poster": "Ron Swanson",
"comment": "Wrong instructions, Got stuck in Toaster"
},
{
"_id": "040412bc-9046-49ca-9a65-19151b32cd91",
"poster": "Tom Haverford",
"comment": "What are Eggs?"
},
{
"_id": "1034f082-b802-4382-be3e-ef50f07a530a",
"poster": "Andy Dwyer",
"comment": "What came firsst, Eggs or Chicken"
}
]
},
{
"_id": "da6f9798-6547-42f5-85ed-043efabeb196",
"title": "Boiled Eggs",
"ingredients": [
{
"name": "Eggs",
"amount": "5"
},
{
"name": "Water",
"amount": "3 Cups"
}
],
"steps": [
"1.Boil the Water",
"2.Add Eggs",
"3. Keepit for 5 mins",
"4. Let it Cool Down",
"5. Peel off the shell"
],
"comments": [
{
"_id": "cc569ebb-1307-499a-b9ee-7b24e557859f",
"poster": "Ron Swanson",
"comment": "Wrong instructions, Got stuck in Oven"
},
{
"_id": "4f02756a-6e1b-4bda-a928-b3c5e03b55d8",
"poster": "Leslie Knope",
"comment": "What are Eggs?"
},
{
"_id": "0f34a5cc-ebe3-41b5-8f0b-6d1a3c206e6b",
"poster": "Andy Dwyer",
"comment": "Can I remove the shell first and then boil?"
}
]
}]
I want to extract only the title and id of both the recipes when a given route is accessed. Currently,I am using this function, which return all the field of both the recipes.
var recipesCollection = db.collection("recipes");
exports.getAllRecipes = function() {
return recipesCollection.find({}).toArray();
};
What query should I use to extract just the title and id of the two recipes and not all the details?

As per my understanding you are trying to fetch specific fields form the mongo collection. You can achieve this just by using the projection.
var recipesCollection = db.collection("recipes");
exports.getAllRecipes = function() {
return recipesCollection.find({}, {"title": 1}).toArray();
};
For more information follow this:
https://docs.mongodb.com/v3.2/tutorial/project-fields-from-query-results/#return-the-specified-fields-and-the-id-field-only

Related

MongoDB Aggregation - How to condition for $set

I am unwinding a lookup joined by { preserveNullAndEmptyArrays: true } option to include documents whose sizes field is null, missing, or an empty array. But in my case, I need to join nested lookup and the output result is not as I expected.
Specifically, I am being to set a new buyer field by the $set operator from lookup but if this lookup is null or empty array it will return [ { } ] and I don't want that. How can I replace [ { } ] with empty array?
The result I got:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"buyers": [
{
"_id": ObjectId("5a934e000102030405000003"),
"buyer": {
"_id": ObjectId("5a934e000102030405000004"),
"display_name": "Phineas",
"user_id": "123"
},
"post_id": 1,
"user_id": "123"
}
],
"content": "content book 1",
"title": "title book 1"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"buyers": [
{}
],
"content": "content book 3",
"title": "title book 3"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"buyers": [
{}
],
"content": "content book 2",
"title": "title book 2"
}
]
The result that I expected:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"buyers": [
{
"_id": ObjectId("5a934e000102030405000003"),
"buyer": {
"_id": ObjectId("5a934e000102030405000004"),
"display_name": "Phineas",
"user_id": "123"
},
"post_id": 1,
"user_id": "123"
}
],
"content": "content book 1",
"title": "title book 1"
},
{
"_id": ObjectId("5a934e000102030405000002"),
"buyers": [],
"content": "content book 3",
"title": "title book 3"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"buyers": [],
"content": "content book 2",
"title": "title book 2"
}
]
Now you can see my code in the Mongo playground link:
https://mongoplayground.net/p/qiC7FySejxF
Comparing your actual output and MongoDB Playground link, I believe that you miss out the $unset stage.
{
$unset: "buyers.buyers"
}
While after the $unset stage, you can add $set stage to update the buyers field by filtering the document which is not empty document via $filter.
{
$set: {
buyers: {
$filter: {
input: "$buyers",
cond: {
$ne: [
"$$this",
{}
]
}
}
}
}
}
Demo # Mongo Playground

Mongoose: Update of array inside another nested array element not working as expected

Here is my mongo schema:
{
"_id": ObjectId("5f8af2fc5f23667adf3bbaf2"),
"score": 2.5,
"questions": [{
"_id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"desc": "some text",
},
{
"_id": ObjectId("5f8af3115f23667adf3bbaf8"),
"desc": "some text",
"options": [{
"_id": ObjectId("5f8af3115f23667adf3bbaf9"),
"name": "some name",
"desc": "description 1"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbafa"),
"name": "some name",
"desc": "description 2"
}
]
}
]
}
I've to update the name and desc of the option having id as 5f8af3115f23667adf3bbaf9 which is in the one of the array elements of the question attribute having id as 5f8af30d5f23667adf3bbaf5 which is again part of the data having id as 5f8af2fc5f23667adf3bbaf2
Tried the following query which is getting executed successfully but not updating the option:
Model.findOneAndUpdate({
_id : ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions._id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"questions.options._id": ObjectId("5f8af3115f23667adf3bbaf9"),
}, {
$set: {
"questions.$[q].options.$[o].order": data.order,
"questions.$[q].options.$[o].definition": data.definition,
"questions.$[q].options.$[o].type": data.type,
},
},
{
arrayFilters: [{ "q._id": ObjectId(qid) }, { "o._id": ObjectId(oid) }]
})
Is tihs possible to do in a single mongoose findOneAndUpdate method?
Your query is correct, I have just hardcoded object id values in array filter and it is updating the documents. I have updated name and desc as u said. Do try this out. One more thing in mongoose u have to specify the object id as "mongoose.Types.ObjectId".
Therefore in your case it would be like "q._id": mongoose.Types.ObjectId("5f8af3115f23667adf3bbaf8").
And one more thing is that you are using findAndUpdate, try using update only depending on your mongoose version
Here is mongoplayground:
https://mongoplayground.net/p/TP5iCTAC5R_
Query:
db.collection.update({
_id: ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions._id": ObjectId("5f8af3115f23667adf3bbaf8"),
"questions.options._id": ObjectId("5f8af3115f23667adf3bbaf9")
},
{
$set: {
"questions.$[q].options.$[o].name": "anotherName",
"questions.$[q].options.$[o].desc": "anotherDesc"
}
},
{
arrayFilters: [
{
"q._id": ObjectId("5f8af3115f23667adf3bbaf8")
},
{
"o._id": ObjectId("5f8af3115f23667adf3bbaf9")
}
]
})
Output :
[
{
"_id": ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions": [
{
"_id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"desc": "some text"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbaf8"),
"desc": "some text",
"options": [
{
"_id": ObjectId("5f8af3115f23667adf3bbaf9"),
"desc": "anotherDesc",
"name": "anotherName"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbafa"),
"desc": "description 2",
"name": "some name"
}
]
}
],
"score": 2.5
}
]

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

MongoDB create product summary collection

Say I have a product collection like this:
{
"_id": "5a74784a8145fa1368905373",
"name": "This is my first product",
"description": "This is the description of my first product",
"category": "34/73/80",
"condition": "New",
"images": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstproduct_image1.jpg"
},
...
],
"attributes": [
{
"name": "Material",
"value": "Synthetic"
},
...
],
"variation": {
"attributes": [
{
"name": "Color",
"values": ["Black", "White"]
},
{
"name": "Size",
"values": ["S", "M", "L"]
}
]
}
}
and a variation collection like this:
{
"_id": "5a748766f5eef50e10bc98a8",
"name": "color:black,size:s",
"productID": "5a74784a8145fa1368905373",
"condition": "New",
"price": 1000,
"sale": null,
"image": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstvariation_image1.jpg"
}
],
"attributes": [
{
"name": "Color",
"value": "Black"
},
{
"name": "Size",
"value": "S"
}
]
}
I want to keep the documents separate and for the purpose of easy browsing, searching and faceted search implementation, I want to fetch all the data in a single query but I don't want to do join in my application code.
I know it's achievable using a third collection called summary that might look like this:
{
"_id": "5a74875fa1368905373",
"name": "This is my first product",
"category": "34/73/80",
"condition": "New",
"price": 1000,
"sale": null,
"description": "This is the description of my first product",
"images": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstproduct_image1.jpg"
},
...
],
"attributes": [
{
"name": "Material",
"value": "Synthetic"
},
...
],
"variations": [
{
"condition": "New",
"price": 1000,
"sale": null,
"image": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstvariation_image.jpg"
}
],
"attributes": [
"color=black",
"size=s"
]
},
...
]
}
problem is, I don't know how to keep the summary collection in sync with the product and variation collection. I know it can be done using mongo-connector but i'm not sure how to implement it.
please help me, I'm still a beginner programmer.
you don't actually need to maintain a summary collection, its redundant to store product and variation summary in another collection
instead of you can use an aggregate pipeline $lookup to outer join product and variation using productID
aggregate pipeline
db.products.aggregate(
[
{
$lookup : {
from : "variation",
localField : "_id",
foreignField : "productID",
as : "variations"
}
}
]
).pretty()

Mongoose - Multi-level navigation

i'm new to MongoDB & Mongoose
I have data like this:
{
"_id": "5787009e494495e56d327417",
"title": "Hahaha",
"parent": null,
"depth": 0
},
{
"_id": "5787009e494495e56d327416",
"title": "Hihihi",
"parent": null,
"depth": 0
},
{
"_id": "5787009e494495e56d327415",
"title": "Huhuhu",
"parent": "5787009e494495e56d327417",
"depth": 1
}
How can I convert the data into this:
{
"_id": "5787009e494495e56d327417",
"title": "Hahaha",
"children": [
"_id": "5787009e494495e56d327415",
"title": "Huhuhu",
"children": []
]
},
{
"_id": "5787009e494495e56d327416",
"title": "Hihihi",
"children": []
}
Please help me, and sorry for my bad english !
There is no other way you have to traverse the result and create new Data in memory.
//for each item in the result {
if(item.parent !=null){
insert_item_in_tree(item);
}
//}
then build a data structure function to insert the one item appropriately as per parent id.

Resources