Filtering documents in mongodb and nodejs - node.js

Data in the database is stored as given below. if I do a query like
const food = await Nutrition.find()
Then I get this in response
[
{
_id: 6035ff4778b1893fa5e8080f,
name: 'apple',
weight: 100,
unit: 'gram',
carbohydrates: 14,
calories: 52,
proteins: 0.3,
fats: 0.2,
__v: 0
},
{
_id: 6036011437035541b0bd5e0a,
name: 'banana',
weight: 100,
unit: 'gram',
carbohydrates: 23,
calories: 89,
proteins: 11,
fats: 0.39,
__v: 0
},
{
_id: 6036011437035541b0bd5e0b,
name: 'melon',
weight: 100,
unit: 'gram',
carbohydrates: 45,
calories: 100,
proteins: 11,
fats: 0.39,
__v: 0
}
]
I have this controller in nodejs which fetch food nutrition from the database
const Nutrition = require('../model/nutritionalFacts')
exports.nutritionFacts = (async (req,res) =>{
try {
const food = await Nutrition.find()
console.log(food);
} catch (error) {
console.log('Error occurred',error.message);
}
})
Now in request (req), req.body is coming as
[
{ name: 'apple', id: 0, selected: true, weight: 100, unit: 'gram' },
{ name: 'banana', id: 1, selected: true, weight: 100, unit: 'gram' }
]
Now I want to filter only those documents from the database whose name matches with the name coming in an array of objects from the client as mentioned above without looping, just using MongoDB query syntax. Can we do this?

You can use $in operator to achieve that. You need to change your find method as below
var namesArr = ["banana", "melon"];
db.Nutrition.find({ "name" : { "$in": namesArr } })
Then the results for the sample above:
{
"_id" : ObjectId("60361058cce08c8b8ebe0509"),
"name" : "banana",
"weight" : 100,
"unit" : "gram",
"carbohydrates" : 23,
"calories" : 89,
"proteins" : 11,
"fats" : 0.39,
"__v" : 0
}
{
"_id" : ObjectId("60361058cce08c8b8ebe050a"),
"name" : "melon",
"weight" : 100,
"unit" : "gram",
"carbohydrates" : 45,
"calories" : 100,
"proteins" : 11,
"fats" : 0.39,
"__v" : 0
}

Try this
const Nutrition = require('../model/nutritionalFacts');
exports.nutritionFacts = (async (req, res) => {
try {
if (!Array.isArray(req.body.payload)) {
throw new Error("Invalid payload!") // or whatever error message u want!
}
const names = payload.map(item => item.name); // u cannot avoid this looping of payload!
const conditions = {
name: { $in: names }
};
const food = await Nutrition.find(conditions);
console.log(food);
} catch (error) {
console.log('Error occurred', error.message);
}
})

Related

Many-many relation Sequelize with variant extra column

I have 3 table, with relation :
User.belongsToMany(Project, { through: Report});
Project.belongsToMany(User, { through: Report});
and my report table has data like :
{ user_id : 1, project_id : 1, percent: 20, date: 20/10/2022}
{ user_id : 1, project_id : 2, percent: 80, date: 20/10/2022}
{ user_id : 2, project_id : 1, percent: 90, date: 20/10/2022}
{ user_id : 1, project_id : 1, percent: 20, date: 21/10/2022}
...
What kind of this many-many relation ? And how can i query project table and get result format like below :
{
"project_id":1,
"users":[
{
"user_id":1,
"reports":[
{
"report_id":1,
"date":"20/10/2022",
"percent":20
},
{
"report_id":1,
"date":"21/10/2022",
"percent":20
}
]
},
....
]
}

mongoose pull command to delete product from shopping cart

CartController.prototype.addToCart =(req, res, next) => {
// Using mongoose in-built function "findbyID"
Product.findById({_id : req.params.productId}).then( item =>
{
if (!item) {res.status(400).send({message : "item not found"})}
Cart.findByIdAndUpdate(req.params.userId,
{
total_quantity : 0,
total_price : 0,
final_price : 0,
"$push": {"products": {
// Passing Data
productid : item._id,
MRP : item.offers.MRP,
finalprice : item.offers.finalprice,
discount : item.offers.discount,
organization : item.property.organization,
brand : item.property.brand,
color : item.property.color,
weight : item.property.weight,
category : item.property.category
}
},
userid : req.params.userId
},
{ upsert: true, returnNewDocument : true}
).then(() => {
res.status(200).send({message: "product added to cart"});
}).catch(err => {
res.status(500).send(err);
});
}).catch (err => {
res.status(500).send("item fetch related issue found", err);
});
};
//json output
[
{
"_id": "5e5a58843ed45a235c32ac8c",
"__v": 0,
"createdAt": "2020-03-16T18:04:31.370Z",
"updatedAt": "2020-03-16T18:41:23.068Z",
"userid": "5e5a58843ed45a235c32ac8c",
"inCart": false,
"products": [
{
"category": "Home Decor",
"weight": 300,
"color": "Multicolor",
"MRP": 5000,
"productid": "5e6f4234564e2d1b74ba3383",
"_id": "5e6fbfaf3818775ac010187e",
"quantity": 1,
"brand": "",
"organization": "",
"discount": 20
},
{
"category": "Home Decor",
"weight": 300,
"color": "Multicolor",
"MRP": 5000,
"productid": "5e6b21458f7019378c4981ff",
"_id": "5e6fbff53818775ac0101881",
"quantity": 1,
"brand": "",
"organization": "",
"discount": 20
}
],
"final_price": 0,
"total_price": 0,
"total_quantity": 0
}
]
//cart model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var product = new Schema({
productid : {
type: Schema.Types.ObjectId,
// required: true,
ref: 'Product'
},
MRP : {
type : Number,
// required : true
},
finalPrice : {
type : Number
},
discount : {
type : Number, default : 0
},
organization : {
type : String, default : null
},
brand : {
type : String, default : null
},
color : {
type : String
},
weight : {
type : Number
},
category : {
type : String,
// required :true
},
quantity : {
type : Number,
// required : true,
default : 1
}
});
var cartSchema = new Schema({
total_quantity : {type : Number, required : true, default: 0},
total_price : {type : Number, required : true, default: 0},
final_price : {type : Number, required : true, default: 0},
products : [product],
userid : {
type: Schema.Types.ObjectId,
required: true,
ref: 'Pujari'
},
inCart : {type : Boolean, default : 0}
},
{
timestamps:true
}
);
module.exports = mongoose.model('Cart', cartSchema);
//delete cart item
CartController.prototype.deleteCartItem = (req, res, next) => {
Cart.update({userid : req.params.userId}, { $pull: { products : {productid: req.params.productId }}}, {multi: true})
};
So, basically I have to collection one for product and another for cart, my question is how to delete particular product from cart like in bellow json I have to product. I just want to delete object where "productid": "5e6b21458f7019378c4981ff", I tried mongodb $pull operator but its not working for this data.
finally I found the solution, there was a small mistake I was doing
//delete cart item
CartController.prototype.deleteCartItem = (req, res, next) => {
Cart.update({userid : req.params.userId}, { $pull: { products : {category: "Home" }}}, function (err, data) {
if (err) res.send(err)
else res.send(data)
})
For me your update is working (for the given document):
db.collection.updateMany(
{ userid: "5e5a58843ed45a235c32ac8c" },
{ $pull: { "products": { productid: "5e6b21458f7019378c4981ff" } } }
)
{
"acknowledged" : true,
"matchedCount" : 1.0,
"modifiedCount" : 1.0
}

MongoDB get remaining seats of restaurant

I've problem to find remaining seats of particular restaurant in a particular Date range
Let me define my problem. Suppose I've a collection it called booking
In this have a following fields:
Booking ID
User ID
Restaurant ID
Booking Start Date (date saved in Timestamp)
Booking End Date (date saved in Timestamp)
Booked Seat
If there are 50 seats in restaurant. And I want to check available seats of a particular date range for example the date range is 6-12(This range in timestamp)"(Start Date) - (End Date)"
How to calculate the total remaining seats of restaurant.
If anyone have any idea please let me know.
Thanks in advance
Code is here
const where = {};
where.restaurant_id = 126;
where.user_id = 1;
where.start_date = { $gte: 6 };
where.end_date = { $gte: 12 };
const remainingSeats = getSeatsAvailability(where);
function getSeatsAvailability(where) {
return new Promise((resolve, reject) => {
bookingModel.find(where, (err, details) => {
if (err) { reject(err); } else { resolve(details); }
});
});
}
So, What I have Visualized is the below diagram, so there are basically four cases to be covered:
x y
a-----------|---------b |
a-|------------|---b
| a-------b |
| a-----|--------b
So the formulae are:
1. a<x, a<y | b>x, b<y
2. a<x, a<y | b>x, b>y
3. a>x, a<y | b>x, b>y
4. a>x, a<y | b<y, b>x
I am pasting an ROUGH example, take it as a hint to solve the problem at hand:
db.collection.aggregate([
{
$match: {
$or: [
{
a: {
$lte: 3,
$lte: 9
},
$or: [
{
b: {
$gte: 3,
$lte: 9
}
},
{
b: {
$gte: 3,
$gte: 9
}
}
]
},
{
a: {
$gte: 3,
$lte: 9
},
$or: [
{
b: {
$gte: 3,
$gte: 9
}
},
{
b: {
$gte: 3,
$lte: 9
}
}
]
}
],
r: 1
}
},
{
$group: {
_id: null,
sum_booked: {
$sum: "$c"
}
}
},
{
$project: {
seats_left: {
$subtract: [
50,
"$sum_booked"
]
}
}
}
])
The example dataset that I have tested on:
[
{
a: 1,
b: 10,
c: 10,
r: 1,
},
{
a: 2,
b: 5,
c: 15,
r: 1
},
{
a: 5,
b: 10,
c: 10,
r: 1
},
{
a: 7,
b: 15,
c: 15,
r: 12 <<<<========/////DIFF REST ID
}
]
Output:
[
{
"_id": null,
"seats_left": 15
}
]
db.booking.aggregate([{
$match: {
BookingStartDate: { $lte: date_range_end },
BookingEndDate: { $gte: date_range_start },
RestaurantID: restaurant_id
}
},
{
$group: {
_id: '$RestaurantID',
TotalBookedSeat: { $sum: '$BookedSeat' }
}
},
{
$project: {
LeftSeat: { $subtract: [50, '$TotalBookedSeat'] },
_id: 0
}
}
])
{ "_id" : ObjectId("5d8479f6902a52448029a6d0"), "bid" : 1, "uid" : 1, "rid" : 126, "bsd" : 1, "bed" : 10, "bs" : 10 }
{ "_id" : ObjectId("5d847a11902a52448029a6d1"), "bid" : 2, "uid" : 1, "rid" : 126, "bsd" : 2, "bed" : 5, "bs" : 15 }
{ "_id" : ObjectId("5d847a24902a52448029a6d2"), "bid" : 3, "uid" : 1, "rid" : 126, "bsd" : 5, "bed" : 10, "bs" : 10 }
{ "_id" : ObjectId("5d847a34902a52448029a6d3"), "bid" : 4, "uid" : 1, "rid" : 126, "bsd" : 7, "bed" : 15, "bs" : 15 }
db.booking.aggregate([{ $match: { bsd: { $lte: 12 }, bed: { $gte: 6 }, rid: 126 } }, { $group: { _id: '$rid', total_seat_sold: { $sum: '$bs' } } }])
The result of the above is 35, then 15 seats left.
This time it will works I think.

MongoDB Query SubDocuments by field valeu

So I have this schema for a Supplier:
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Address = require('./Address.js'),
AddressSchema = mongoose.model('Address').schema,
Product = require('./Product.js'),
ProductSchema = mongoose.model('Product').schema;
// Create a new schema for the reviews collection with all the relevant information for a review
var Schema = mongoose.Schema;
var Supplier = new Schema(
{
name: String,
address: AddressSchema,
location: {
type: {type:String, default: 'Point'},
coordinates: [Number] // [<longitude>, <latitude>]
},
products: [ProductSchema]
}
);
Supplier.index({location: '2dsphere'});
var SupplierModel = mongoose.model('Supplier', Supplier );
// export the review model
module.exports = SupplierModel;
Products in my system have a "verified" field which is a boolean. In one of my routes I would like to query the DB to find all the suppliers which have products which aren't verified such that I can then render those products in the page.
I tried this, but unofrtunatelly it returns all the subdocuments no matter if "verified" is true or false:
exports.admin_accept_product_get = function (req, res) {
Supplier.find({'products.verified' : false}, function(err, docs) {
res.render('admin_accept_product', { user : req.user, suppliers: docs });
});
};
Any help is appreciated
Edit:
The previous query would return the following data:
{
"_id" : ObjectId("5b2b839a2cf8820e304d7413"),
"location" : {
"type" : "Point",
"coordinates" : [
-16.5122377,
28.4028329
]
},
"name" : "Tienda1",
"products" : [
{
"verified" : true,
"_id" : ObjectId("5b2b83d32cf8820e304d7420"),
"title" : "Vodka",
"inStock" : 15,
"typeOfItem" : "alcohol",
"sellingPrice" : 15,
"image" : "public/upload/15295784515201529168557789bottle.png",
"typeOfAlcohol" : "vodka"
},
{
"verified" : false,
"_id" : ObjectId("5b2b848f8c59960c44df09cd"),
"title" : "Whisky",
"inStock" : 40,
"typeOfItem" : "alcohol",
"sellingPrice" : 15,
"image" : "public/upload/15295786395491529323314298whisky.png",
"typeOfAlcohol" : "whisky"
}
],
"__v" : 2
}
I would like my query to not return the firt product because "verified == true"
You need to use $elemMatch to find the document and $elemMatch for projection of the data
db.collection.find({
products: {
$elemMatch: {
verified: false
}
}
},
{
products: {
$elemMatch: {
verified: false
}
},
location: 1
})
Output
[
{
"_id": ObjectId("5b2b839a2cf8820e304d7413"),
"products": [
{
"_id": ObjectId("5b2b848f8c59960c44df09cd"),
"image": "public/upload/15295786395491529323314298whisky.png",
"inStock": 40,
"sellingPrice": 15,
"title": "Whisky",
"typeOfAlcohol": "whisky",
"typeOfItem": "alcohol",
"verified": false
}
]
}
]
Check it here

Find objects in deep Mongo DB docs

I've got a Mongo DB doc with a teams array. All the objects in the teams array contain a user_ids array. How do I find all documents containing a team where user_ids contains a specific Object Id? I'm using Mongoose with Node.
This is the doc structure. How would I eg find all docs with Object Id "56a60da2351195cc6be83799" in any of the teams?
{
"_id" : ObjectId("56a60da3351195cc6be8379c"),
"session_id" : ObjectId("56a60da2351195cc6be83798"),
"teams" : [
{
"score" : 0,
"user_ids" : [
ObjectId("56a60da2351195cc6be83799")
]
},
{
"score" : 0,
"user_ids" : [
ObjectId("56a60da2351195cc6be8379a")
]
}
],
"created_at" : ISODate("2016-01-25T11:57:23.006Z") }
Thanks
Let's say your collection name is collection, try:
db.collection.find({"teams.user_ids": ObjectId("56a60da2351195cc6be83799")})
It will find a document, if exists matching user_ids
For nested arrays the $in operator will be a good choice (see documentation).
I tried to reproduce your settings and created a simple model:
var testSchema = mongoose.Schema({
session_id: { type: Number },
teams : [
{
score: { type: Number },
user_ids: [{ type: Number }]
}
]
})
var Test = mongoose.model("Test", testSchema);
Inserted demo data:
var test1 = new Test({
session_id: 5,
teams: [
{ score: 5, user_ids: [ 1, 2, 4] },
{ score: 3, user_ids: [ 2, 7, 9 ] },
{ score: 1, user_ids: [ 3 ] },
]
});
test1.save(function(err, t1) { console.log("test", err, t1); });
var test2 = new Test({
session_id: 1,
teams: [
{ score: 5, user_ids: [ 11, 12 ] },
{ score: 3, user_ids: [ 1, 9 ] },
]
});
test2.save(function(err, t2) { console.log("test", err, t2); });
The query to get all objects with a userId of 2 would look like:
Test.find({ "teams.user_ids": { $in: [2] }}, function(err, res) {
console.log("query:", err, res);
});
Or in a more mongoose way of reassembling queries:
Test.find()
.where('teams.user_ids')
.in([2])
.then(result => { console.log(result); })
.catch(err => { console.log(err); });

Resources