Mongoose - Find with and array - node.js

I have an array of objects : userNames , that contains
[
{
name:"alice"
},
{
name:"jhon"
}
]
and I have collection Users , I want to find users that theirs names are in userNames array without forEach ...

You can use mongo $in operator to search by array values. Example:
const users = userNames.map(user => user.name);
User.find({ name: { $in: users } }).then(users =>
console.log("There you are: ", users)
);

Related

finding multiple documents with mongoose

this is what happens when I console.log()
this is what happens when I return all documents with that id, I just get the first document
const followingUsers = await User.find({ _id: { $in: foundUser.followings } })
const getFeedData = async() => {
for (let user of followingUsers) {
for (let postId of user.posts) {
console.log(postId)
}
}
}
I'm running this code when I console.log(postId) it returns all the posts with that id, but when I try to retrieve all documents with that id it returns just one document
findById will only return one record or null, an ID is the _id field on each document in a collection, which is a unique value
find is the equivalent of a where command in SQL, it returns as many documents that match the query, or an empty array
passing $in as a query to find looks for an array of matching document for the user id's
so if you already know the document _id's, then find will return the ID's so long you have passed an array of valid ObjectId
// (pretending these are real id's)
const arrayOfUserIds = [
ObjectId("5af619de653438ba9c91b291"),
ObjectId("5af619de653438ba9c91b293"),
ObjectId("5af619de653438ba9c91b297")
]
const users = await User.find({ _id: { $in: arrayOfUserIds } })
console.log(users.length)
users.forEach((user, index) => {
console.log(`${index} - `, user._id)
})
// => 3
// => 0 - ObjectId("5af619de653438ba9c91b291")
// => 1 - ObjectId("5af619de653438ba9c91b293")
// => 2 - ObjectId("5af619de653438ba9c91b297")

MongoDB data matching and fetching issue while querying on an array

I want to fetch data from the MongoDB. Since I am new into Node.Js and MongoDB. I am not able to get the data.
I am passing primary category and secondary category to an API where I want to match the primary and secondary category with the array field "category" which is having two indexes 0 and 1 ,in the 0 index primary category is there and in the 1 index secondary categories are there separated by ~ .
Below is my code to get the data according to primary category but I want to get the data by matching the primary and secondary category from the db.
ProductModel
.find({ category : { $all : [req.body.primary] }})
.select('id link brand title description category image images in_stock price sale_price merchant_number part_number GroupID status promotion attributes tags currency updated -_id')
.then((productList) => {
response.status = 200;
response.msg = 'Success';
response.count = productList.length;
response.data = productList
res.json(response);
})
.catch(() => {
response.status = 500;
response.msg = 'connection error';
response.data = [];
res.json(response);
});
Sample Doc :
So I wanted to input something like ['Health','women'] & get docs where all of these elements in category array exists, kind of regex search on array elements.
Can Someone help me out to get the data from the db.
If you've to query with input as ['Health', 'women'] & get the documents which has both listed & also get the documents which has something like this : category : ["Health", "tes~men~women"] then you can try below query :
Query :
db.collection.find({
$and: [
{
category: {
$in: [
/\bwomen\b/
]
}
},
{
category: {
$in: [
"Health"
]
}
}
]
})
Js Code :
const secondary = req.body.secondary
const primary = req.body.primary
db.collection.find({
$and: [
{
category: {
$in: [
new RegExp(`\\b${secondary}\\b`, 'i')
]
}
},
{
category: {
$in: [
primary
]
}
}
]
})

Get 2 documents in 1 MongoDB call

I am using MongoDB and Mongoose to retrieve documents from the database.
I have two IDs and I want to get the corresponding documents. I use
Collection.findById(id1).then(doc1 => {
if (doc1) {
Collection.findById(id2).then(doc2 => {
if (doc2) {
Is it possible to do this in a single call?
I am wondering if it can be done with
{doc1, doc2} = Collection.find({ _id: $in: [id1, id2] });
and if this is better than my original approach.
You can use mongoDB $in operator to retrieve multiple documents, the syntax is
db.inventory.find( { id: { $in: [ 5, 15 ] } } )

Mongoose - find() with multiple ids that are the same

If I were to perform this query with mongoose;
Schema.find({
_id: {
$in: ['abcd1234', 'abcd1234', 'abcd1234']
}
});
The query will only return something like:
[{
'property1': 'key1',
'property2': 'key2'
}]
With the array only having one object, obviously because I passed in all the same id's. However, I actually want duplicate objects returned. How can I do this?
Mongo itself will only return objects with no duplicates. But you can then build an array of objects with duplicates from that.
For example, if array is the array of objects returned my Mongo - in this case:
var array = [{
_id: 'abcd1234',
property1: 'key1',
property2: 'key2'
}];
and ids is your list of IDs that you want with duplicates - in your case:
var ids = ['abcd1234', 'abcd1234', 'abcd1234'];
then you can do:
var objects = {};
array.forEach(o => objects[o._id] = o);
var dupArray = ids.map(id => objects[id]);
Now dupArray should contain the objects with duplicates.
Full example:
var ids = ['abcd1234', 'abcd1234', 'abcd1234'];
Schema.find({_id: {$in: ids}}, function (err, array) {
if (err) {
// handle error
} else {
var objects = {};
array.forEach(o => objects[o._id] = o);
var dupArray = ids.map(id => objects[id]);
// here you have objects with duplicates in dupArray:
console.log(dupArray);
}
});

mongodb/mongoose findMany - find all documents with IDs listed in array

I have an array of _ids and I want to get all docs accordingly, what's the best way to do it ?
Something like ...
// doesn't work ... of course ...
model.find({
'_id' : [
'4ed3ede8844f0f351100000c',
'4ed3f117a844e0471100000d',
'4ed3f18132f50c491100000e'
]
}, function(err, docs){
console.log(docs);
});
The array might contain hundreds of _ids.
The find function in mongoose is a full query to mongoDB. This means you can use the handy mongoDB $in clause, which works just like the SQL version of the same.
model.find({
'_id': { $in: [
mongoose.Types.ObjectId('4ed3ede8844f0f351100000c'),
mongoose.Types.ObjectId('4ed3f117a844e0471100000d'),
mongoose.Types.ObjectId('4ed3f18132f50c491100000e')
]}
}, function(err, docs){
console.log(docs);
});
This method will work well even for arrays containing tens of thousands of ids. (See Efficiently determine the owner of a record)
I would recommend that anybody working with mongoDB read through the Advanced Queries section of the excellent Official mongoDB Docs
Ids is the array of object ids:
const ids = [
'4ed3ede8844f0f351100000c',
'4ed3f117a844e0471100000d',
'4ed3f18132f50c491100000e',
];
Using Mongoose with callback:
Model.find().where('_id').in(ids).exec((err, records) => {});
Using Mongoose with async function:
const records = await Model.find().where('_id').in(ids).exec();
Or more concise:
const records = await Model.find({ '_id': { $in: ids } });
Don't forget to change Model with your actual model.
Combining Daniel's and snnsnn's answers:
let ids = ['id1', 'id2', 'id3'];
let data = await MyModel.find({
'_id': {
$in: ids
}
});
Simple and clean code. It works and tested against:
"mongodb": "^3.6.0",
"mongoose": "^5.10.0",
Use this format of querying
let arr = _categories.map(ele => new mongoose.Types.ObjectId(ele.id));
Item.find({ vendorId: mongoose.Types.ObjectId(_vendorId) , status:'Active'})
.where('category')
.in(arr)
.exec();
This code works for me just fine as of mongoDB v4.2 and mongoose 5.9.9:
const Ids = ['id1','id2','id3']
const results = await Model.find({ _id: Ids})
and the Ids can be of type ObjectId or String
Both node.js and MongoChef force me to convert to ObjectId. This is what I use to grab a list of users from the DB and fetch a few properties. Mind the type conversion on line 8.
// this will complement the list with userName and userPhotoUrl
// based on userId field in each item
augmentUserInfo = function(list, callback) {
var userIds = [];
var users = []; // shortcut to find them faster afterwards
for (l in list) { // first build the search array
var o = list[l];
if (o.userId) {
userIds.push(new mongoose.Types.ObjectId(o.userId)); // for Mongo query
users[o.userId] = o; // to find the user quickly afterwards
}
}
db.collection("users").find({
_id: {
$in: userIds
}
}).each(function(err, user) {
if (err) {
callback(err, list);
} else {
if (user && user._id) {
users[user._id].userName = user.fName;
users[user._id].userPhotoUrl = user.userPhotoUrl;
} else { // end of list
callback(null, list);
}
}
});
}
if you are using the async-await syntax you can use
const allPerformanceIds = ["id1", "id2", "id3"];
const findPerformances = await Performance.find({
_id: {
$in: allPerformanceIds
}
});
I tried like below and it works for me.
var array_ids = [1, 2, 6, 9]; // your array of ids
model.find({
'_id': {
$in: array_ids
}
}).toArray(function(err, data) {
if (err) {
logger.winston.error(err);
} else {
console.log("data", data);
}
});
I am using this query to find the files in mongo GridFs. I wanted to get the by its Ids.
For me this solution is working: Ids type of ObjectId.
gfs.files
.find({ _id: mongoose.Types.ObjectId('618d1c8176b8df2f99f23ccb') })
.toArray((err, files) => {
if (!files || files.length === 0) {
return res.json('no file exist');
}
return res.json(files);
next();
});
This is not working: Id type of string
gfs.files
.find({ _id: '618d1c8176b8df2f99f23ccb' })
.toArray((err, files) => {
if (!files || files.length === 0) {
return res.json('no file exist');
}
return res.json(files);
next();
});

Resources