Question

I'm trying to create a simple search-function in SailsJS (beta), using the waterline ORM for data handling. My function in my controller does the search using the predefined find()-method of waterline.

I wonder, is it possible to send an SQL-regexp pattern to the waterline find()-function to make it fetch all users having a matching REGEXP?

My find-method in my controller contains this (except the regexp functionality, which I'm asking for):

// Replace any spaces with SQL regex wildcards
var regexp = req.body.search.replace(' ', '*');

  // Show found users
  User.find()
  .where({
    or: [
      {username: { contains: req.body.search }},
      {email: { contains: req.body.search }},
      {fullName: { regexp: regexp }}
    ]
  }).exec(function(err, users){

    if (err){
       return res.send(403, 'Failed to find users' + JSON.stringify(err));
    }

    res.view('userlist', {
      users: users
    });

  });

The fullName attribute is defined as an instance method within the attributes, and is probably not searchable. However, is there a way to make a decent search for names?

This is an extract from my User model:

module.exports = {
  attributes: {
    firstName: {
      type: 'string'
    },
    lastName: {
      type: 'string'
    },
    fullName: function(){
      return this.firstName + ' ' + this.lastName;
    },
    (...some more attributes, as well as email and username...)
  }
}

How do i make the find()-method work with SQL regex? My goal is to make a search for "Hans Eikerol" display "Hans Martin Eikerol" in the result set.

Was it helpful?

Solution

Waterline maps .find() to the underlying find syntax for the database you're connected to. It doesn't support regular expressions because regex is not supported by all of the database adapters. One could argue that since regular expression search comes standard with most mainstream databases these days, that the feature might have a place in Waterline, but in the meantime you can use .query to do a native SQL query. Then you coerce the results back to Waterline models. For example, with sails-mysql:

User.query("[some sql query using RLIKE]", function(err, rows) {
    if (err){
        return res.send(403, 'Failed to find users' + JSON.stringify(err));
    }

    res.view('userlist', {
        // Map the rows returned by the query to Waterline instances
        users: rows.map(function(row){return new User._model(row);});
    });
});

OTHER TIPS

Author Edit:

Thanks for the answer:) However, I managed to find a suitable solution to my problem without having to use regex pattern search. This is my new controller method:

  var split = req.body.search.split(' ');

  // Assume last piece of search is the lastName, ignore middlenames
  var firstName = split[0];
  var lastName = split.pop();

  // Show found users
  User.find()
  .where({
    or: [
      {username: { contains: req.body.search }},
      {email: { contains: req.body.search }},
      {firstName: { contains: firstName }},
      {lastName: { contains: lastName }},
      {firstName: {startsWith: firstName}, lastName: lastName}
    ]
  }).exec(function(err, users){

    if (err){
       return res.send(403, 'Failed to find users' + JSON.stringify(err));
    }

    res.view('admin/users', {
      users: users
    });

  });
thanks a lot for your answer, I have implemented something like this, using waterline on sails:
.find({  $and:[{"userType":"basic"},{"name":{contains:req.params.name}} ] })
    .exec(function(err,seller){
      if(err){
        res.send(err);
      }else{
        console.log(seller);
        res.send(seller)
      }
    })
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top