Search feature using mongoose - node.js

I am creating an application using mean stack. I need to create a advanced search feature for my application where schema can searched by various fields like firstname, lastname, etc. On clicking the search button I will use the below route to connect to the server.
$http.get('/search/' + $routeParams.searchdata)
now if I try to console log the searchdata I can get the fields that I entered in the search form. Eg: If I enter the first name and the email id I see in the console as
{"firstname": "Smith", "email": "smith#gmail.com"}
If I try to access searchdata.firstname I get undefined.
1) How can I access the fields entered in the search form?
2) There are many fields in the schema. How will I tell to search only the fields that were entered in the form?

1) How can I access the fields entered in the search form?
See this answer Node.js: Difference between req.query[] and req.params
2) There are many fields in the schema. How will I tell to search only the fields that were entered in the form?
Just pass the query to your find mongoose function like this :
app.get('yourPath', function(req, res){
yourCollection.find(req.query, function(err, elements){
if(err)
res.status(500).send(err);
else{
res.json(elements);
}
}

Related

Not able to access the data inside of an object

I am fetching id column value from database for a particular email. In this case I am passing email and want to get primary key i.e id. This operation is successful as I get object which contains Object with the right and expected result. However I am not able to access the object.
I am receiving object like this:
[ UserInfo { id: 21 } ]
And I am not able to access id part of it.
I am using node.js, postgres for database and typeorm library to connect with database.
const id = await userRepo.find({
select:["id"],
where: {
email:email
}
});
console.log(id)
This prints the above object.
The id I am getting is right. But I am not able to retrieve the id part of the object. I tried various ways for e.g.
id['UserInfo'].id, id.UserInfo.
Please help me in accessing the object I am receiving
Typeorm .find() returns an array of objects containing entries corresponding to your filters, in your case, all entries with an email field corresponding to the email you specified.
Because the result is an array, you can access it this way:
const records = await userRepo.find({
select: ['id'],
where: {
email,
},
})
console.log(records[0].id)
You could also use the .findOne() method, which returns a single element and might be a better solution in your case :)
When you are putting a field in the select part select:["id"], you are only retrieving this part of the database.
It is like your query was this: select id from userRepo where email = email
and you need to put * in the select part to retrieve all the information:
const id = await userRepo.find({
select:["*"],
where: {
email:email
}
});

Express, Mongoose, db.findOne always returns same document

I am attempting a CRUD app with MEAN stack. I am using mongoose in Express to call to the MongoDB. I am using the FindOne function with a specified parameter, and it's always returning the same (incorrect) document.
I know I am connected to the correct database, since I get a document back from that collection, but it's always the same document, no matter what I pass as the parameter.
module.exports = mongoose.model('Player', playersSchema, 'players'); //in player.js
const Player = require('./model/players');
app.get('/api/player/:id', (req, res) =>{
Player.findOne({id: req.params.playerId},
function(err, player) {
if(err) {
res.json(err);
}
else {
res.json(player);
}
});
});
I have 3 separate "players", with three distinct "playerID" fields (38187361, 35167321, 95821442). I can use Postman to GET the following URL, for example:
http://localhost:3000/api/player/anythingyouWantInHere
and it will return 38187361, the first document. I've been over this website, many tutorials, and the Mongoose documentation and I can't see what I'm doing wrong..
I'd like to eventually find by playerId OR username OR email, but one hurdle at a time...
From the mongoose documentation of findOne, if you pass Id a null or an empty value, it will query db.players.findOne({}) internally which will return first document of the collection everytime you fetch. So make sure you are passing non-empty id here.
Note: conditions is optional, and if conditions is null or undefined,
mongoose will send an empty findOne command to MongoDB, which will
return an arbitrary document. If you're querying by _id, use
findById() instead.
Your route is '/api/player/:id', so the key on the req.params object will be 'id' not 'playerId'.
I don't know what/where/if you're populating the playerId param, but if you update your query to call req.params.id it should actually change the document based on the path as you seem to be wanting to do.
I had the same problem, and it was that the name of column's table was different from the model I had created.
In my model the name of the wrong column was "role" and in my table it was "rol".

Expressjs (node) - How to get a set of data which is filtered according to the user

I am new to express js. I am currently building a todo list web app. I have been following the tutorials and is able to perform basic CRUD operation. I have two models.
Users - (name, email, password hash, password salt, todo_items - which reference to the second model).
Todo_items - (title, description, due_date, user - which reference to the first model).
When a user log in, I am able to read his user_id. However, how can i filter the todo_items that only belongs to the user? My current code looks like this and is returning all the todo_items from all the users.
router.get('/api/todo_items', function(req, res, next){
Todo_items.find(function(err,todo_items){
if(err){return next(err); }
res.json(todo_items);
})
});
Currently, I am using a front end framework, Angularjs to filter the results that get displayed. But I thought this is inefficient as the user base gets big. How do I create a filtering system from the backend?
You can query the collection on the user field, assuming it references the User model on the _id field so you could have something like the following:
router.get('/api/todo_items', function(req, res, next){
Guest.find({ "user": user_id }).exec(function(err, todo_items){
if(err) { return next(err); }
res.json(todo_items);
});
});

Return the value from a mongoose find

I'm trying to render a template when i check the link for view a profile (for example going to http://localhost:3000/user/testuser`), all ok going to the routes but the values don't being showed on the page. This is my code:
Account.find({ username: req.params.username }, function(err, userWatch){
res.render('account/profile',{
title : userWatch.username,
user : req.user,
watchUser : userWatch,
});
You are using Account.find() that returns the array of objects. You should use Account.findOne() to fetch data, if you want either one or none objects.

Creating view to check a document fields for specific values (For a simple login)

I'm very new to cloudant , so pardon me for this question. I am creating a simple mobile game login system which only checks for username(email) and password.
I have several simple docs that are in this format
{
"_id": "xxx",
"_rev": "xxx",
"password": "3O+k+O8bxsxu0KUlSBUiww==", --encrypted by application beforehand
"type": "User",
"email": "asd#asd.com"
}
Right now I can't seem to get the correct 'Formula' for creating this view (map function) whereby I would do a network request and pass it both the email and password. If there is a doc that matches the email, then check the doc.password against the passed value. If it matches, the function should return a simple "YES".
For now my map function is as follows, but this just returns all the docs .
function(doc) {
if (doc.email){
index("password", doc.password, { store : true });
if (doc.password){
emit("YES");
}
}
}
It may be my request format is also wrong. Right now it is as follows. Values are not real, only for format checking
https:/etcetc/_design/app/_view/viewCheckLogin?q=email:"asd#asd.com"&password:"asd"
It looks like you have misunderstood how views are supposed to work. In general you cannot perform logic to return a different result based on the request. Query parameters in a view request can only be used to limit the result set of view entries returned or to return grouped information from the reduce function.
To determine if there is a match for a given username and password you could emit those values as keys and then query for them. This would return the view entry for those keys or an empty list if there was no match. However I'd be very cautious about the security here. Anyone with access to the view would be able to see all the view entries, i.e. all the usernames and passwords.

Resources