mongoose count() function with regex case insensitive matching sub string also - regex

I am trying to find out a simple solution to handle case sensitive email using regex, so far it works good when inserting/querying the document using Mongoose but when I'm validating if the user exists using the Model.count method, its not working as expected.
I have defined this static function in the schema, which takes the username and return the count of occurance in the collection.
userSchema.statics.exist = function(username, cb){
this.count({ "username": new RegExp(username, "i") }, cb);
};
and I have a controller function which calls this static like this:
userExist: function (req, res) {
UserModel.exist(req.body.username, function (err, count) {
res.json({exist: count});
});
}
if I pass user#example.com in the req.body.username field ( where user#example.com exist in the database), it returns 1
but its returning 1 even if I enter I enter user#examp or user#exampl or user#example.c
Not sure what I'm doing wrong, I thought it may be issue with regex, so I tested this regex for validity:
var username = "user#example.com";
var pattern = new RegExp(username, "i");
pattern.match("user#examp"); // this returns false
Any help is appreciated. Thanks !

I was able to solve this issue by changing the regex a little bit like this:
userSchema.statics.exist = function(username, cb){
this.count({ "username": new RegExp('^'+username+'$', 'i') }, cb);
};
Hope this helps someone. Any other suggestions are welcome

Related

node.js - sending regex to server

I've created a client side mongodb interface to talk to server side mongodb.
it's very similar to the mini-mongo implemented in the meteor.
here is an example:
model.find({"field": /search/}).exec(function(err, model){
construct(model);
});
now normally everything works fine except when I use the regex.
and I know what's the problem but I cannot fix it.
the problem, as you have guessed it, is when the regex /regexParameter/ when sent by ajax to server, is converted to "/regexParameter/" and the single quotes(or double) make the regex a normal string.
in the server I have something like this:
var findObject = req.query.findObject // {"field": "/search/"} :(
req.models[config.table]
.find(findObject)
.exec(function(err, model){
return res.json({
error: err,
result: model,
});
});
is there anything I can do to make this work without writing like 100 of lines of code that iterates through each of the findObject and matches every string for a regex...?
Thanks everyone
You are right - you cannot pass RegExp objects between client and server because during serialization they are converted to strings.
Solution? (or perhaps - a workaround)
Use $regex operator in your queries, so you don't need to use RegExp objects.
So this:
{
field: /search/
}
Becomes this:
{
field: {
$regex: 'search'
}
}
Or, giving a case-insensitive search example:
{
field: {
$regex: 'search',
$options: 'i'
}
}
(instead of field: /search/i)
Read more about $regex syntax here (including about some of its restrictions).

Meteor subscriptions using deps

I'm trying to implement a searching feature in a Meteor application that re-subscribes/publishes a collection on every search, so there is only the exact Collection necessary in the client. I'm creating a reactive variable searchString, then changing it to the text in the search box on every search, then splitting the string into tags:
// Client
var searchString = "";
var searchStringDep = new Deps.Dependency;
var getSearchString = function(){
searchStringDep.depend();
return searchString;
}
var handle = Deps.autorun(function(){
var tags = getSearchString().split(" ");
tags = _.map(tags, function(tag){
return tag.replace(/[^\w]/g, "");
}).filter(function(t){
return t.toLowerCase();
});
Meteor.subscribe('results', tags);
});
Template.library.events({
'submit form': function(ev){
ev.preventDefault();
searchString = ev.target.search.value;
searchStringDep.changed();
}
})
Then, publishing a new Collection on the server, based on the tags:
// Server
Meteor.publish('results', function(tags){
regTags = _.map(tags, function(tag) { return new RegExp(tag)});
return Samples.find({tags: {$in: regTags}})
});
So I'm trying to match on regexes, but am having a weird issue where the subscription only changes when I add another tag, but changing existing tags fails.
So if the first searchString was tag1 and the second tag1 tag2, it works fine.
But if the first is tag1 and the second is tag2, the Collection doesn't update.
Any help is appreciated...I'm a beginner to Meteor, so if there is a better way to do what I'm trying to do, all suggestions are welcome. Thanks so much
'change #search': function(){
Meteor.subscribe('sampleResults', $('#search').val()); // or if you want on submit it's the same idea
}
and publish like
Meteor.publish('sampleResults, function(text){
return Samples.find({tags: {$regex: text}});
}
A few things:
1) Meteor has a very nice way of setting up reactive variables with the ReactiveVar component. I would suggest using that rather than creating another dependency for a variable.
2) The name that you are subscribing to: results is different than what is published on the server sampleResults and that can cause issues.
3) If you are on Meteor >= 0.9.1 you should be using Tracker and not Deps. You can use Deps if you want, but the new updated API is Tracker and is probably more stable. See the changelog for more details on that.
4) You don't have to set your Deps.autorun function equal to a variable. So you can have it as:
Tracker.autorun(function() {
// Code here
});

How can i use regex in mongodb over mongolab?

My question is simple but i can not find exact solution. All articles have gor below a line of code:
collection.findOne({hello:'world_no_safe'});
Above codes does work and returns to me undefined error.But it is existed. Anyway, My exact solution is above. Please help me and teach me how to use regex by searching inside of the json api. ı want to use %mysearch data% as a regex expression. ı want to make text search which is used all sentences in json.
For example : i have a json:
[{"data":"Andreas Kollegger explains what kinds of questions you can answer with a graph database. It's not only the big sites that "},{"data":"X explains what kinds of questions you can answer with a graph database. It's not only the big sites that "}]
if i use this expression: collection.findOne({hello:'%Andreas%'});
it has to return first data. Below a real sample from my project.
var mongo = require('mongodb');
var Server = mongo.Server;
var Db = mongo.Db;
var server = new Server('ds053479.mongolab.com', 53479, {auto_reconnect : true});
var db = new Db('orient', server);
db.open(function(err, client) {
client.authenticate('testname', 'fsfsff', function(err, success) {
var collection = db.collection('Models');
collection.insert({Name:'test1'});
// Fetch the document
collection.findOne({Name:'%world_no_safe%'});
});
According to the MongoDB Manual you can use the $regex operator:
collection.findOne({Name: { $regex: '.*world_no_safe.*' }});

Twitter Typeahead remote

I am trying to use Twitter typeahead but I am facing a problem. I don't know how typeahead passes the string to the server. Is it through a GET parameter? If so, what is the name of the parameter?
Easiest through a GET parameter, you can choose whatever parameter you want.
In JS:
$('#search').typeahead({
name: 'Search',
remote: '/search.php?query=%QUERY' // you can change anything but %QUERY, it's Typeahead default for the string to pass to backend
});
In PHP (or whatever backend you have):
$query = $_GET['query'];
Hope you get the basic idea.
You might want to consider something like this, it is a very basic remote datasource example. The get parameter in this example is 'q'
// Get your data source
var dataSource = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'path/to/your/url/json/datasource/?q=%QUERYSTRING',
wildcard: '%QUERYSTRING'
}
});
// initialize your element
var $typehead = $('#form input').typeahead(null, {
source: dataSource
});
// fire a select event, what you want once a user has selected an item
$typehead.on('typeahead:select', function(obj, datum, name) {
//your code here
});
////////////////////////////////////
# in python (django) we get a query string using the request object passed through a view like this
query = request.GET.get('q') or ""
//the caveat [or ""] is just to prevent null exceptions
///////////////////////////////////
# using php
$query = ($_GET['q']) ? $_GET['q'] : "";

Express.JS regular expression for example.com/:username

// ex: http://example.com/john_smith
app.get('/^(a-z)_(0-9)', function(req, res) {
res.send('user');
});
// ex: http://example.com/john_smith/messages/1987234
app.get('/^(a-z)_(0-9)/messages/:id', function(req, res) {
res.send('message');
});
I wrote the above code for an app that I want to pass a username as a url variable to node.js like I would do: $username = $_GET['username']; in PHP. I'm not too good at writing regular expressions so I wanted to see if anyone could set me on the right track. Thanks in advance.
From your requirement it doesn't seem like you need a regular expression. Just use a a variable in your rule, like below:
// Grabs whatever comes after /user/ and maps it to req.params.id
app.get('/user/:id', function (req, res) {
var userId = req.params.id;
res.send(userId);
});
If you want to have better control, you could use a regular expression. To grab things you are interested in from the expression, use a capture group (which are typically expressed as a set of matching parenthesis):
// Grabs the lowercase string coming after /user/ and maps it to req.params[0]
app.get(/^\/user\/([a-z]+)$/, function (req, res) {
var userId = req.params[0];
res.send(userId);
});
A little off topic, but here's a really good intro to express.js that will help you understand it better (including how the routes work):
http://evanhahn.com/understanding-express-js/
You're looking for req.params, which is an array of all of the capture groups in the regex.
The capture groups start at 1; req.params[0] is the entire match.