mongoDB find, update and pull in One Query - node.js

I want to do all the find the data from the collection and then want to update some field as well as depending on want to empty the array.
const addCityFilter = (req, res) => {
if (req.body.aCities === "") {
res.status(409).jsonp({ message: adminMessages.err_fill_val_properly });
return false;
} else {
var Cities = req.body.aCities.split(","); // It will make array of Cities
const filterType = { "geoGraphicalFilter.filterType": "cities", "geoGraphicalFilter.countries": [], "geoGraphicalFilter.aCoordinates": [] };
/** While using $addToset it ensure that to not add Duplicate Value
* $each will add all values in array
*/
huntingModel
.update(
{
_id: req.body.id,
},
{
$addToSet: {
"geoGraphicalFilter.cities": { $each: Cities }
}
},
{$set:{filterType}},
).then(function(data) {
res.status(200).jsonp({
message: adminMessages.succ_cityFilter_added
});
});
}
};
Collection
geoGraphicalFilter: {
filterType: {
type:String,
enum: ["countries", "cities", "polygons"],
default: "countries"
},
countries: { type: Array },
cities: { type: Array },
aCoordinates: [
{
polygons: { type: Array }
}
]
}
But as result, the only city array is getting an update. No changes in filterType.

You appear to be passing the $set of filterType as the options argument, not the update argument.
huntingModel
.update(
{
_id: req.body.id,
},
{
$addToSet: {
"geoGraphicalFilter.cities": { $each: Cities }
},
$set: {
filterType
}
}
).then(function(data) {
res.status(200).jsonp({
message: adminMessages.succ_cityFilter_added
});
});

Related

count nested array inside documen using updateOne() function

const reset_qr_list_and_update_count = await stock_read_log.updateOne(
{
payload: {$ne:req.body.payload},
"qr_list.payload": req.body.new_qr_list[indexx].payload,
company_id:req.body.company_id
},
{
"$pull": {
"qr_list": {
payload: req.body.new_qr_list[indexx].payload
}
},
$set:{
qty: xx
},
}
);
$set:{
qty: model.aggreation({
//the query
}).count()
},
after pulling one of the list above,i want to re-count list left ,how can i achieve that within this function?

check an array of string value with array of object in mongodb

I have array of strings like this
let fromHour = ['2.5','3','3.5']
let toHour = ['2.5','3','3.5']
I have an array of object saved in mongoDB
timeRange = [
{
from:'2.5',
to:'3'
},
{
from:'3',
to:'3.5'
}
]
I want to check if any of my array of string value exist in that object value
I have tried this but it give me this error ( Unrecognized expression '$match' )
checkAppoint = await Appointment.aggregate([
{
$project: {
date: myScheduleFinal[k].date,
status: { $in: ['pending', 'on-going'] },
timeRange: {
'$match': {
'from': { $in: fromHolder },
'to': { $in: toHolder },
},
},
},
},
]);
also I have tried this solution and it work for me but it take to much time so I am trying this with aggregate
checkAppoint = await Appointment.findOne({
date: myScheduleFinal[k].date,
status: { $in: ['pending', 'on-going'] },
timeRange:{$elemMatch:{
from:{$in:fromHolder},
to:{$in:toHolder}
}}
});
So anyone have a solution for that
Just try $elemMatch and $in operators,
using find() method
checkAppoint = await Appointment.find({
timeRange: {
$elemMatch: {
from: { $in: fromHour },
to: { $in: toHour }
}
}
})
Playground
using aggregate() method
checkAppoint = await Appointment.aggregate([
{
$match: {
timeRange: {
$elemMatch: {
from: { $in: fromHour },
to: { $in: toHour }
}
}
}
}
])
Playground
So I have found a way around to solve this problem and I will share the solution I used
First I want to minimize my request to mongodb so I am now making just one request that bring all the appointment with the required date
and I want to make it this way because my fromHour and toHour array will change many time through single request
helperArray => contains all the day I want to check it's range
let checkAppoint = await Appointment.find({
date: { $in: helperArray },
status: { $in: ['pending', 'on-going'] },
});
now inside my for loop I will go through that data
checkAppoint.filter((singleAppoint) => {
if (singleAppoint._doc.date === myScheduleFinal[k].date) {
singleAppoint._doc.timeRange.map((singleTime) => {
if (fromHolder.includes(singleTime.from)) {
busy = true;
}
});
}
});

mongoose delete from array

I need to remove the user's id from all objects in the collection except the one that was passed, in my example it is value: 'Тата', tell me how to make such a request?
console.log(result)
[
{
_id: 5fa702b2f18e5723b4c00d9f,
value: 'Тата',
vote: { '36e7da32-f818-4771-bb5e-1807b2954b5f': [Array] },
date: 2020-11-07T20:25:22.611Z,
__v: 0
}
]
console.log(req.body)
{ value: 'Тата', habalkaId: '36e7da32-f818-4771-bb5e-1807b2954b5f' }
console.log(req.user._id)
5f63a251f17f1f38bc92bdab
that's all I could do, just find
router.post('/', passport.authenticate('jwt', {session: false}), (req, res) => {
FirstName.find({value: req.body.value})
.then(result => {
if (result.length) {
console.log(result)
console.log(req.body)
console.log(req.user._id)
FirstName.find({value: {$ne: 'Слоник'}}, function (err, arr) {
arr.map(e => {
if (e.vote[req.body.habalkaId].length) {
if(e.vote[req.body.habalkaId].includes(String(req.user._id))){
console.log(e.vote[req.body.habalkaId])
}
}
})
})
} else {
new FirstName({
value: req.body.value,
vote: {[req.body.habalkaId]: [String(req.user._id)]}
}).save();
}
})
// res.json({res: req.body})
})
FirstName.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const FirstNameSchema = new Schema({
value: {
type: String
},
vote: {
type: Object
},
date: {
type: Date,
default: Date.now
}
});
module.exports = FirstName = mongoose.model('firstname', FirstNameSchema);
If I've understand well, you want something like this:
db.collection.update({
"value": {
"$ne": "tata"
}
},
{
"$pull": {
"vote.array_name": "id_value"
}
},
{
multi: true
})
First of all, find all document that not match the value with the given one. Then, for each document found, delete the object from the array, using $pull where the id given matches.
Example here
Please check the payground and check if I've used the correct schema and it shows the expected output.

Mongoose multiple optional 'and' conditions

I am trying to filter a collection with 3 optional 'and' conditions.
Here is my model:
const Company = mongoose.model(
'Company',
new Schema({
name: { type: String },
sectors: [{ type: Schema.Types.ObjectId, ref: 'Sector' }],
industries: [{ type: Schema.Types.ObjectId, ref: 'Industry' }],
countries: [{ type: Schema.Types.ObjectId, ref: 'Country' }],
})
And my component:
const getCompanies = (skip, limit, filter) =>
Company.find({
...filter.countries && { countries: filter.countries },
...filter.sectors && { sectors: filter.sectors },
...filter.industries && { industries: filter.industries },
})
.skip(skip)
.limit(limit)
.sort({ date: -1 })
.populate('countries')
.populate('sectors')
.populate('industries');
const getAll = async (req, res) => {
try {
const countries = req.query.country;
const sectors = req.query.sector;
const industries = req.query.industry;
const skip = parseInt(req.query.skip, 10);
const limit = parseInt(req.query.limit, 10);
const filter = {
...countries && { countries },
...sectors && { sectors },
...industries && { industries },
};
const result = await getCompanies(skip, limit, filter);
return res.status(200).json(result);
} catch (e) {
return res.status(500).send({ message: (e.message) });
}
};
This is working when the filter is empty, but when there is one or more items in the filter, I get an empty array.
If I hard code data in getCompanies like so:
Company.find({
countries: '5d5e913e20c01070fef5c77e',
sectors: '5d5e913e20c01070fef5c754',
industries: '5d5e913e20c01070fef5c7ad',
})
or :
Company.find({
countries: '5d5e913e20c01070fef5c77e'
})
I get the data I want.
I also tried to console.log the filter in getCompanies to make sure the data was correct, and I get this if all fields are requested:
{
countries: '5d5e913e20c01070fef5c77e',
sectors: '5d5e913e20c01070fef5c754',
industries: '5d5e913e20c01070fef5c7ad',
}
and this for just one:
{ countries: '5d5e913e20c01070fef5c77e' }
So it seems fine to me.
I also tried using '$and' like so:
Company.find({ $and: [
{ ...filter.countries && { countries: filter.countries } },
{ ...filter.sectors && { sectors: filter.sectors } },
{ ...filter.industries && {industries: filter.industries } },
],
})
or using '$in':
Company.find({
...filter.countries && { countries: { $in: filter.countries } },
...filter.sectors && { sectors: { $in: filter.sectors } },
...filter.industries && { industries: { $in: filter.industries } },
})
But no luck either.
Here is a sample URL:
GET /api/internal/member/get?skip=12&limit=6&country=5d5e913e20c01070fef5c77e&sector=&industry=
I have found some other threads with questions somewhat similar to mine, but they were to different to help me solve my case.
Looking forward to your helpful advice.
I finally got it to work. Turns out I was not clearing the data in the frontend at each change, which caused an issue with the skip/limit fields.
I also changed the find as advised by #whoami like so:
Company.find({ $and: [
{
...filter.countries && { countries: { $in: [mongoose.Types.ObjectId(filter.countries)] } },
...filter.sectors && { sectors: { $in: [mongoose.Types.ObjectId(filter.sectors)] } },
...filter.sdgs && { sdgs: { $in: [mongoose.Types.ObjectId(filter.sdgs)] } },
}
],
})

Sails-mongo. Find in array

I'm using sails.js and sails-mongo adapter. Suppose I have a model:
module.exports = {
attributes: {
shema: true
, attributes: {
description: {
type: 'TEXT'
, max: 200
}
, tags: {
type: 'ARRAY'
}
}
}
};
How can I carry out a search in an tags array?
Model.find({
'tags.title': {
contains: 'query'
}
})
.done(function (err, response) {
/**/
});
db.schools.find( { criteria },
{ atributes: { $elemMatch: { tags: value } } } )
there are a great example here: http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/
with waterline
Model.native(function(err, collection) {
// Execute any query that works with the mongo js driver
collection.find( { criteria },
{ atributes: { $elemMatch: { tags: value } } } )
});

Resources