Searching in mongodb using just few keywords - javascript

I'm using node js,mongoose,express and mongodb.
I have created simple form, in which you enter you full name and it searches in database and return your other details .
Is it possible to search using only few words out of the whole name? e.g. if the user wants to search for "abc xyz",can user do the same using only "abc" or "xyz"
this is my original route:
app.get("/",function(req,res){
var name = req.query.name;
details.findOne({fullname:name},function(err,foundAsked){
if(err){console.log("ERROR!!!");}
else{res.render("Details.ejs",{foundAsked:foundAsked,name:name}); }
});
});
Is it possible to do that?if yes,then how can I implement that ?

You could use regex to partially match on certain fields like so
const query = {
fullname: {
$regex: req.query.name,
$options: 'i'
}
};
details.find(query, function(err, foundAsked){
...
})
Where the i in query is to make it case insensitive.
In the case of using partial search, I would recommend not using findOne as that might be misleading to the user to only return a single result if he/she types let's say A

Yes, you can use regexes for that :
details.findOne({ fullname : /.*(?:abc|xyz).*/gi }, .....

Related

TypeORM findby Child Properties of a MongoDB Document

I have a MongoDB document in the following format. I can verify that it exists in MongoDB using Compass. I'm using TypeORM to make the query, not MondoDB.
{
_id: 'some id'
user: {
details: {
email: "test#test.ch",
username: "testname"
},
status: 'active'
}
}
Is it possible to use TypeORM to find by, say, the email?
I've tried
const emailExists = await this.userRepo.findOneBy({
user: {
details: {
email: "test#test.ch"
}
}
});
but emailExists always returns null even though I can validate that it exists in MongoDB. I've tried other ways to find by email using find, findOne, and more.
How do you find a matching value of a child property, like email? Is there a better approach?
MongoDB: Query on Nested Field
To specify a query condition on fields in an embedded/nested document, use dot notation.
Example: 'field.nestedField'
When querying using dot notation:
The field and nested field must be inside quotation marks.
Applying in your code:
const emailExists = await this.userRepo.findOneBy({'user.details.email': 'test#test.ch'});
Reference:
MongoDB Official Documentation: Query on Embedded/Nested Documents
Update: Looks TypeORM not work well with MongoDB, but you can try use $match.
Example:
$match : { 'field.nestedField': nestedField }
Applying in your code:
this.userRepo.findOneBy({$match: { 'user.details.email': 'test#test.ch' }});
If not work maybe try to change TypeORM to Mongoose.
Reference:
https://github.com/typeorm/typeorm/issues/2483

Best way to escape array of data on MysQl nodeJS query

So I have the following object with is made by data submitted by the user in order to sign up:
var dataToInsert = {
userName: 'Wilson J',
userEmail: 'WilsonJ#gmail.com',
userAddress: '2020 St.',
userCellPhone: '95587412',
}
And I'm using the following query to insert it:
var insertQuery = `INSERT INTO users ( ${Object.keys(dataToInsert).toString()} ) VALUES( '${Object.values(dataToInsert).join("','")}' )`;
Which at the end is taken as:
INSERT INTO
users (
userName,
userEmail,
userAddress,
userCellPhone
)
VALUES
(
'Wilson J',
'WilsonJ#gmail.com',
'2020 St',
95587412
)
So far I'm having a hard time understanding how data escaping works. I'd really appreciate if someone could show me how a SQL Injection could take place with this code and how to prevent it.
I'm using the MysQl npm module and it has this method: mysql.escape() but I would like to find a more automated approach instead of escaping every single value manually.
In this day and age, it's actively discouraged to do anything other than bind variables to your query. See this for more information on other ways to escape data:
connection.query(`
INSERT INTO users ( ${Object.keys(dataToInsert).toString()} ) VALUES (?)`,
Object.values(dataToInsert),
function (error, results, fields) {
if (error) throw error;
// ...
}
);
Word of caution: You wont be able to bind variables to the column names, so unfortunately that part of the query is necessary. Ensure your keys of your dataToInsert are either static, or not from any user input.
Alternatively, you can use ? characters as placeholders for values you would like to have escaped like this: [...]
There is a way. https://github.com/mysqljs/mysql#user-content-escaping-query-values

Find in a collection based on an array in user's profile

Sorry if this is a basic question, I'm relatively new to javascript and Meteor.
I'm trying to create a recommended page that recommends sites that you have upvoted. It takes the tags that are on the post, and puts them into the user profile under 'tags' as an array.
var websiteTags = Websites.findOne(website_id, {fields: {tag: 1} });
var getTags = websiteTags.tag;
Meteor.users.update(this_user, {$addToSet: {"profile.tags": getTags}});
Then under the templates helper, I'm trying to return a list of websites that have the tags equal to what is in the users profiles.
Template.user_recommended_list.helpers({
websites:function(){
var usersTags = Meteor.user().profile.tags;
return Websites.find({tag: usersTags});
}
});
If I add an index number like: Meteor.user().profile.tags[0], it will work, but I need to query multiple user tags against the website tag list.
I've tried looping through the users tags then return each value to the page, but it wouldn't work. What's the best way to do it?
Thanks in advance
Just use the $in operator in your mongo query:
return Websites.find({tag: {$in: usersTags}});

MarkLogic: find by property value

I have a MarkLogic 8 database:
declareUpdate();
var book0 = {
id: fn.generateId({qwe: 'book'}),
username: 'book',
password: 'pass'
};
var book1 = {
id: fn.generateId({asd: 'book'}),
username: 'user',
password: 'pass1'
};
xdmp.documentInsert(
'zz' + book0.id,
book0,
xdmp.defaultPermissions(),
['qwe']);
xdmp.documentInsert(
'xx' + book1.id,
book1,
xdmp.defaultPermissions(),
['qwe']);
So I want to find them by name with the Node.js API:
var db = marklogic.createDatabaseClient(connection.connInfo);
var qb = marklogic.queryBuilder;
function findByName(name) {
return db.documents.query(
qb.where(
qb.collection('qwe'),
qb.value('username', name)
)
).result();
}
The problem is that it finds not only user or user0, but also users and if I create a document with username book it will find both book and books.
A values query matches the entire text of a JSON property by stemming each word in the text (if stemming is enabled, which is the default).
Where (as in this case) that's not what you want, you can do either of the following:
Create a string range index (with the root collation if you only need exact matches) for the JSON property
Turn on word searches in the database configuration and use the "unstemmed" option on the query.
If you also turn off stemmed search in the database configuration, you don't have to pass the option (and avoid the extra resource required for both types of indexes).
To limit the configuration change to a specific property, you can configure a field for the property instead of configuring the entire database.
For more background, see:
http://docs.marklogic.com/guide/search-dev/stemming
http://docs.marklogic.com/guide/admin/text_index
http://docs.marklogic.com/cts.jsonPropertyValueQuery?q=cts.jsonPropertyValueQuery&v=8.0&api=true
Hoping that helps,

Mongoose: Adding an element to array

I'm using Drywall to create a website.
I'm trying to add a dashboard element to the accounts section of the admin site. The dashboard element is to store an array of dashboards (strings) that the user has access to.
I've managed to successfully add the "dashboards" into the schema and store data in it.
Here's the problem:
I need to be able to add elements to the array. The way the code stands currently replaces the contents of dashboards in the database.
I know I can use $addToSet, but I'm not sure how I'd do that since the fieldsToSet variable is sent to the findByIdAndUpdate() method as a single object.
Here's the snippet of my code:
workflow.on('patchAccount', function() {
var fieldsToSet = {
name: {
first: req.body.first,
middle: req.body.middle,
last: req.body.last,
full: req.body.first +' '+ req.body.last
},
company: req.body.company,
phone: req.body.phone,
zip: req.body.zip,
search: [
req.body.dashboards,
req.body.first,
req.body.middle,
req.body.last,
req.body.company,
req.body.phone,
req.body.zip,
]
};
req.app.db.models.Account.findByIdAndUpdate(req.params.id, fieldsToSet, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
workflow.outcome.account = account;
return workflow.emit('response');
});
});
Here's a link to the original file: (lines 184-203)
Thanks!
fieldsToSet is a bad name (at least misleading in this case), the parameter is actually update which can take $actions like $addToSet
I don't think you want to set (only) the search field with dashboards. I'm guessing that field is used to index users for a search. So you'll probably wind up doing something like this:
fieldsToSet = {
....all the regular stuff,
$addToSet: {dashboard: req.body.dashboardToAdd}
//I'm not sure that you can add multiple values at once
}
Since this is setting all of the values each time I'm not sure you actually will want to add single dashboard items. Instead you might want to get the full set of dashboards the user has and set the whole array again anyway (what if they removed one?)
fieldsToSet = {
....all the regular stuff,
dashboards: req.body.dashboards
//In this case you'd want to make sure dashboards is an appropriate array
}

Categories

Resources