Multiple where with $or sequelize - javascript

I trying get all users by provided emails using where clause and $or in sequelize.
Where in sequelize
So i created query from my emails array for multiple where like this:
[ { email: 'email1#gmail.com' }, { email: 'email#gmail.com' } ]
Then i try to get it in many way for example like that:
const allExistedUsers = await User.findAll({
where: { $or: multileWhere }
});
According to answer in this post and doc it should work:
{ $and: [{"Key1": "Value1"}, {"Key2": "Value2"}] }
But it does not work. I can't figure out how to do it.

Your E-Mails as Array:
const mails = [ { email: 'email1#gmail.com' }, { email: 'email#gmail.com' } ];
const yourEmailsArray = mails.map( el => { return el.email; });
Then you can concat your E-Mails. Sequelize formats in:
WHERE (`User`.`email` = 'email1#gmail.com' OR `User`.`email` = 'email2#gmail.com')
const allExistedUsers = await User.findAll({
where: {
email: { [Op.or]: [].concat(yourEmailsArray)}
}
});

I did it using another approach from this post
here
const allExistedUsers = await User.findAll({
where: { email: { [Op.or]: usersEmailsToAssign } }
});
usersEmailsToAssign is a array with strings

Related

How do I turn list of strings to list of ObjectIds in Node JS?

I'm using mongoose and I have the following list:
const ids: ["63bd7878f1f085f7d8a6827f", "63be730bf1f085f7d8a682c8"];
I want to turn ids into a list of ObjectIds..
I've tried the following:
const affectedUsers = await Users.find(
{ _id: { $in: [ids.map(e => mongoose.Types.ObjectId(e))] } }
);
But it gives me the following error:
"message": "Cast to ObjectId failed for value \"[\n new
ObjectId(\"63bd7878f1f085f7d8a6827f\"),\n new
ObjectId(\"63be730bf1f085f7d8a682c8\")\n]\"
(type Array) at path \"_id\" for model \"users\""
You have added extra brackets at $in query, try this...
const affectedUsers = await Users.find(
{ _id: { $in: ids.map(e => mongoose.Types.ObjectId(e)) } }
);
You should remove the extra array in the $in operator, like so:
const affectedUsers = await Users.find(
{ _id: { $in: ids.map(e => mongoose.Types.ObjectId(e)) } });

map() returns undefined error after Mongoose populate

const form = await Form.findOne({ _id: res._id }).populate({
path: "activity.viewedBy",
model: User,
});
const a = await form.activity.map((a) => a.viewedBy);
console.log(a.map((e) => e.email));
"Cannot read property 'email' of undefined"
Why?
a is an array, full of objects, like this:
[
{
id: 123,
email: example#email.com
},
{
id: 456,
email: nice#email.com
}
]
Edit, sharing the whole async function:
const viewForm = async (req, res) => {
const form = await Form.findOne({ _id: res._id }).populate({
path: "activity.viewedBy",
model: User,
});
const a = await form.activity.map((a) => a.viewedBy);
console.log(a.map((e) => e.email));
await Form.updateOne(
{ _id: res._id },
{
$push: {
activity: {
viewedBy: res.user,
date: new Date(),
},
},
}
);
return {
statusCode: 200,
body: JSON.stringify(`Form viewed.`),
};
};
Edit2:
There was an undefined in the array, among the objects, I didn't notice that... That's why I was getting the undefined.
a probably has a different structure than you think (try console.log(a)), just proving:
const data = [
{
id: 123,
email: "example#email.com"
},
{
id: 456,
email: "nice#email.com"
}
];
const result = data.map((a) => a.email);
console.log(result);
Also, giving your variables meaningful names can help to prevent mistakes.
await form.activity.map((a) => a.viewedBy);
will return an array of viewedBy values. So the array a doesn't contain the full objects. Instead, it contains an array of viewedBy elements.
Also, please take a look at the functionality of the map() function.

How to use pop and push in one query with mongoose?

Is it possible to do this two "operation" in one query
const deleteUser = await BOQ.findOneAndUpdate({_id:req.params.id}, { $pop: { user: 1 }});
const assignUser = await BOQ.findOneAndUpdate({_id:req.params.id}, {$push:{user: req.params.userId}})
If it possible can anyone tell me how ?
I try
const deleteUser = await BOQ.findOneAndUpdate({_id:req.params.id}, { $pop: { user: 1 }},
{$push: {user: req.params.userId}});
But it won`t work
const deleteUser = await BOQ.findOneAndUpdate(
{ _id: req.params.id },
{
$pop: { user: 1 },
$push: { user: req.params.userId }
}
);
The second paramter is a document of update operators. You can refer the documentation for more detail on the parameters.

How to distinct query and get last data date? (parse server)

like js code
when I do this
it will query up to 1000 times,
can it query once?
const promises = idList.map(async id => {
const query = new Parse.Query("results");
query.equalTo("id", id);
query.descending("createdAt");
query.first()
});
const prPool = await Promise.all(promises);
You need to use aggregate. It would be something like this:
const pipeline = [
{ match: { id: id } },
{ sort: { createdAt: -1 } },
{ group: { objectId: '$id', lastCreatedAt: { $first: '$createdAt' } } }
];
const query = new Parse.Query('results');
const prPool = await query.aggregate(pipeline);

Promise.all() is slower than using await for each promise?

I'm doing some testing for performance and was looking at Promise.all() in node/js. However, after testing this it's actually slower than using await for the 3 promises I want to resolve. I'm simply returning some data back from a mongodb database.
Am I doing something wrong here or is this just due to the way the event loop is working?
Promise.all() : 234.820ms
// Init db connection
const db = client.db('docker-client1');
const productsCollection = db.collection('ICProductData');
const rulesCollection = db.collection('SPRuleData');
const customersCollection = db.collection('ARCustomerData');
// Main function
const CustomerCode = 'FINE';
const ProductCode = 'BEDCABINET';
let customers = customersCollection
.find({ _id: CustomerCode })
.project({ PriceCode: 1, BillToAccountCode: 1 })
.toArray();
let products = productsCollection
.find({ _id: ProductCode })
.project({ 'Price.PriceCode': 1, 'Price.SellingPrice': 1 })
.toArray();
let rules = rulesCollection
.find({
$and: [
{
$or: [
{
$and: [
{ What1Code: ProductCode, What1Type: 'Product' },
{ Who1Code: CustomerCode, Who1Type: 'Customer' }
]
}
]
}
]
})
.toArray();
const results = await Promise.all([customers, products, rules]);
console.timeEnd();
Simply using await : 127.239ms
// Init db connection
const db = client.db('docker-client1');
const productsCollection = db.collection('ICProductData');
const rulesCollection = db.collection('SPRuleData');
const customersCollection = db.collection('ARCustomerData');
// Main function
const CustomerCode = 'FINE';
const ProductCode = 'BEDCABINET';
const custReq = await customersCollection
.find({ _id: CustomerCode })
.project({ PriceCode: 1, BillToAccountCode: 1 })
.toArray();
const prodReq = await productsCollection
.find({ _id: ProductCode })
.project({ 'Price.PriceCode': 1, 'Price.SellingPrice': 1 })
.toArray();
let rulesReq = await rulesCollection
.find({
$and: [
{
$or: [
{
$and: [
{ What1Code: ProductCode, What1Type: 'Product' },
{ Who1Code: CustomerCode, Who1Type: 'Customer' }
]
}
]
}
]
})
.toArray();
console.timeEnd();
The method toArray() does not return a Promise in Old versions of Mongo. This could be the explanation about timings. You could put a console.log with timing after each toArray() they should run in the same millisecond (same tick). If this is not the case, it could be an indication that toArray() is waiting for the response... so you are running sequentially. You could try to resolve this with: let myProm = collection.find(filter).exec()

Categories

Resources