Mongoose .find() with unique filter - node.js

I have a big DB with some duplicate items. Can I use .find() with filter by unique field? If I use .distinct('term') it return an array of unique terms like ['term1', 'term2', 'term3'], but I want to return an array with entire objects from db, filtered by unique 'term'.

I resolved it by filtering the response from .find()
responses = await Product.find({ product_id: data.input });
let container = [];
responses
.filter((value, index, self) => {
return (
self.findIndex((v) => v.search_term === value.search_term) === index
);
})
.map((ele) => {
container.push(ele);
});

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")

Find a records by where clause with nested object values

I want to do a multi-search, if .where by "sku" ain't giving any results, proceed to search for a values by additional_attributes.refKey
Any idea on how to find a records in firestore based on nested object value, such as these:
const ref = db.collection('products')
let snapshot = await ref.where('sku', '==', req.query.id).get()
if (snapshot.empty) {
snapshot = await ref.where('additional_attributes', 'array-contains', req.query.id).get()
if (snapshot.empty) return res.json([])
}
const collection = []
snapshot.forEach(doc => {
collection.push({ id: doc.id, ...doc.data() })
})
res.json(collection)
I've tried also in this way:
snapshot = await ref.where('additional_attributes', 'array-contains', { refKey: req.query.id }).get()
But it didn't gave me any results either. Any idea what I'm doing wrong ?
You need to use dot notation to access nested properties:
await ref.where('additional_attributes.refKey', '==', req.query.id)
// ^^^^^^
You can use the same method to use other operators such a array-contains if you are looking for an element in an array.

MongoDB How to check if all ObjectIds inside the array exist in the database?

I have an array containing multiple mongodb ObjectId, how can I know if all that Ids exist in the specific collection,
Although I can achieve my expected result by for loop like this, it will take too long to load because it will make multiple query for how many index my array has.
const queryData = async objectIds => {
// objectIds contains an array of ObjectId
for (let i = 0; i < objectIds.length; i++) {
const objId = objectIds[i]
const data = await DataCollection.findOne({ _id: objId })
if (!data) throw new Error('Data not found!')
}
}
how can I achieve the same result as my sample function without querying multiple times that makes the process so much slower?
You can use .count() and $in for filtering condition:
let count = await DataCollection.count( { _id: { $in: objectIds } } );
let all = count === objectIds.length;

Firebase Nodejs - after get listCollections

I want to get a collection of subCollections,
admin.firestore()
.collection(SCHEDULE_COLLECTION)
.doc(user)
.listCollections()
.then(collections => {
const cId = [];
collections.forEach(collection => {
});
return res.send(cId);
})
.catch(err => {
console.log(err);
return res.status(500).send(err);
});
I'm getting here ID,
Now I want to get the collections under
this object
How I can do it?
Thanks
Those are not subcollections. What you circled are fields in a single document. Just read build a reference to the document and read it like you normally would with get(). "events" and "foods" will be array type fields in the document snapshot.
const ref = admin.firestore()
.collection(SCHEDULE_COLLECTION)
.doc(user)
.collection(collection)
.doc(...)
.get()
You'll have to query the collection to get the list of documents if you don't know the document ID.

How to send bulk MongoDB count() queries?

My application has a search field and to do an autocomplete, I first fetch the distinct() values, and immediately after, I send a count() query for each distinct value. There can be dozens of values to then count, that's a lot of queries.
Any idea how I could avoid this large number of queries using MongoDB's NodeJS module?
For now, the query is as such:
const baseQuery = {
"organization": organization,
"status": "processed"
}
let domains = []
// A. Query to get the disinct values
MongoDB.getMainCollection().distinct(`location.hostname`, { organization, status: "processed" })
// B. Got the value, now creating a COUNT() query for each
.then(list => {
domains = list.map((host,idx) => Object.assign({}, { domain: host, count: 0, idx: idx }))
const countingPromises = list.map(host => MongoDB.getMainCollection().count(Object.assign({}, baseQuery, { "location.hostname": host })))
return Promise.all(countingPromises)
})
// C. Putting it all together
.then(values => {
values.forEach((count, idx) => {
const domain = domains.find(d => d.idx === idx)
if (domain) {
domain.count = count
}
})
domains.sort((a,b) => b.count - a.count)
resolve(domains)
})
.catch(err => reject(new AppError(`Error listing hostnames for #${organization}.`, 500, err, payload)))
p.s. this works as intended and returns what I want -- just want to avoid so many queries and perhaps bundle them if possible?
You can get all the distinct values and their counts in a single aggregate query:
MongoDB.getMainCollection().aggregate([
// Filter for the desired docs
{$match: baseQuery},
// Group the docs by location.hostname and get a count for each
{$group: {_id: '$location.hostname', count: {$sum: 1}}}
])

Resources