How can I loop over a list of documents and execute commands on each in mongoose with async await - mongodb

I have users, posts and follows collection. I want to select posts, limit it to 10 and look their authors in follows collection whether user follow him or not. Also using async and await made me confusing. I tried this code
async function index (req,res){
const {user_id} = req.body
const post = await Post.find().exec( async (err,doc)=>{
const isFollowing = await Follows.find({who_id : user_id , whom_id : doc._id })
if (isFollowing.length > 0){
return doc
}
})
Then I figured out from VS Code that if I use exec function "'await' has no effect on the type of this expression.

You can select 10 random posts and return only the one that the user follows between them with:
async function index (req,res)
{
const { user_id } = req.body
const posts = await Post.find().limit(10);
const following = [];
for (const post of posts) {
const isFollowing = await Follows.find({ who_id : user_id , whom_id : post._id });
if (isFollowing) following.push(post);
}
return following;
})

Related

How to use Array contains in the same array fields in firebase for flutter

I have a chat collection.
each document has an array with two user id's.
my goal is to get the chat that has both user sys id's
I tried running the following but I got an error because we cant use two 'arrayContains' in one query.
Is there any way to perform such query?
here is an image of the data structure
Future getChat({required List userIdsArr}) async {
var docId = '';
userIdsArr.sort((a, b) {
return a.compareTo(b);
});
var filter1 = userIdsArr[0];
var filter2 = userIdsArr[1];
await chat
.where(userIdsArrayColumn, arrayContains: userIdsArr[0])
.where(userIdsArrayColumn, arrayContains: userIdsArr[1])
.get()
.then((value) {
value.docs.forEach((element) {
docId = element.id;
});
});
return docId;
}
the goal is to get the chat that pertains to the users being passed in userIdsArr
this seems to work, is there a better way of doing this?
Future getChat({required List userIdsArr}) async {
var docId = '';
userIdsArr.sort((a, b) {
return a.compareTo(b);
});
await chat
.where(userIdsArrayColumn, arrayContains: userIdsArr[0])
// .where(userIdsArrayColumn, arrayContains: userIdsArr[1])
.get()
.then((value) {
value.docs.forEach((element) {
if (element[userIdsArrayColumn].contains(userIdsArr[1])) {
log('match found!');
docId = element.id;
}
});
});
return docId;
}
A query can only contain a single array-contains query.
To allow your query, you'll want to add an additional field to the document where you keep the pair of UIDs in a predictable (e.g. alphabetical) order. With such a field you can then use a query such as:
where("concatenated_uids", isEqualTo: userIdsArr[0]+"_"+ userIdsArr[1])

How to filter Data using email in MongoDB?

How can I get data by email from MongoDB? Here is an example:
_id: Objectid('6274e58826914a298567e5f8'),
"name": "Vauxhall Mokka",
"supplier": "Vauxhall",
"email": "abc#def.com",
"price": 30000,
"quantity": 30,
"img": "https://i.ibb.co/SQqBNXy/getImage.png",
"sold": 0
I can easily get the item by _id with this code:
app.get('/cars/:id', async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await serviceCollection.findOne(query);
res.send(result);
});
But why I couldn't do the same with email? when I apply '/cars/:email', the server goes down. If I get the item with id, then why cannot get it with the email?
No reason why this shouldn't work
app.get('/cars/:email', async (req, res) => {
const query = { email: req.params.email };
const result = await serviceCollection.findOne(query);
res.send(result);
});
When the "server goes down", is it giving you an error message?
Your email is missing in node js code you have to grave email from req as like this
const email = req.query.email
the problem is you already have another endpoint with "/cars/" you need to change "/(here)/" ... like "/carsByEmail/:email". This happens when you declare another same endpoint with app.get method. You should try this enter code here
app.get('/carsByEmail/:email', async (req, res) => {
const query = { email: req.params.email };
const result = await serviceCollection.findOne(query);
res.send(result);
});
you already have this endpoint, this two are (1)=> "/cars/:id" and (2)=> "/cars/:email" the same get method. so that's why it's giving you BSONType error. and it also collaborates with the other same endpoint. So you should change the main endpoint name.. Like (1)=> "/carsById/:id" and (2)=> "/carsByEmail/:email" now everything is perfect withe the same get/put/patch method. just change the main part of the API endpoint. Thank you
app.get('/cars/:id', async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await serviceCollection.findOne(query);
res.send(result);
});

Changing order of an array in mongoose does not save

I am using drag and drop library to change the order of my elements, and I need that order to be saved, the following method does change the document but it won't save it, I tried doc.save() and this update method, the logged doc is in changed order but it's not updated in the database.
module.exports.changeListOrder = async(req, res) => {
const { id, listID, oldIndex, newIndex } = req.body;
await Board.findById(id).then(async(doc) => {
let tmpdoc = doc.lists[oldIndex];
doc.lists[oldIndex] = doc.lists[newIndex];
doc.lists[newIndex] = tmpdoc;
await Board.updateOne({ _id: id }, { $set: { list: doc.lists } })
});
}
and my model has
lists: [{ header: String, listItems: Array }]
You are mixing up Promise and async syntax. The async syntax would be like this:
module.exports.changeListOrder = async (req, res) => {
const { id, listID, oldIndex, newIndex } = req.body;
const thisBoard = await Board.findById(id);
// this code won't run until thisBoard has returned a value
let [oldValue, newValue] = [thisBoard.lists[oldIndex], thisBoard.lists[newIndex];
thisBoard[oldIndex] = newValue;
thisBoard[newIndex] = oldValue;
let saveOperation = await Board.save(thisBoard);
// console.log(saveOperation);
// return saveOperation or do something with res()
};
module.exports.changeListOrder = async(req, res) => {
const { id, listID, oldIndex, newIndex } = req.body;
const doc = await Board.findById(id);
let [oldValue, newValue] = [doc.lists[oldIndex], doc.lists[newIndex]];
doc.lists.set(oldIndex, newValue);
doc.lists.set(newIndex, oldValue);
await doc.save();
};
Here is the working code, the problem was that Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value, so you have to use set()

Mongoose findOne variables

I have a function which passes a key val and then gets added as arguments for a .findOne() mongoose function.
getByKey = async (key, val) => {
console.log(key, val);
const user = await UserSchema.findOne({
key: val
});
console.log(user);
return user;
};
The problem is, I think mongoose is actually searching the collection for the word key instead of the what it stands for ie: "username" or "age"
It is looking for 'key' as opposed to the key your passing. You can accomplish what you're trying to do by doing something like this.
var query = {}
query[key] = value;
And then pass that query to your findOne function. See below.
getByKey = async (key, val) => {
var query = {}
query[key] = value;
const user = await UserSchema.findOne(query);
console.log(user);
return user;
};
You also might want to consider adding a callback function to in your findOne and try to log the data if it was found.
const user = await UserSchema.findOne(query, function(err, data){
if (err){
console.log(err)
} else {
console.log(data)
}
});
You can use Computed property names to handle this. Example:
const user = await UserSchema.findOne({
[key]: val
});

How to make a request to receive random documents based on id? limit(10)

Firestore(web)
Help me write a request for random documents based on ID
Can I do this without getting the entire collection?
const questions = [];
const docRef = db.collection('ru').doc(category).collection('questions');
try {
const doc = await docRef.get();
doc.forEach((item) => {
questions.push(item.data());
});
} catch (e) {
throw e;
}