Manmohan
Manmohan

Reputation: 85

MVC ASP.Net LINQ syntax to search for any or part of string

I'm attempting to search in a column for ANY of the words in the search string(space de-limited). I'm able to search for whole string (using .Contains) but not ANY of the words it is made of.

eg: search_field = {apples, pears, bananas, grapes}

search_string = "Apples" ==> works fine,

search_string = "apples bananas" ==> 0 results as it tries to find exact string literal

I'm looking for a way to find all words (search_string.Split??) and return all matches.

The below works for single word searches currently,

public ActionResult Search(string search_string)
    { return view(db.AttributesTable.Where(
       x => x.Description.Contains(search_string)).ToList());
}

Can someone please help me adapt this to return ANY of the words in ANY ORDER within the search_string?

i.e search_string (apples, bananas) or (bananas, apples) should return same results.

Thanks.

Upvotes: 3

Views: 2024

Answers (5)

NetMage
NetMage

Reputation: 26946

This is a good use of .Any:

public ActionResult Search(string search_string) {
    var srchTerms = search_string.Split(new[] { ' ' });
    return view(db.AttributesTable.Where(
       x => srchTerms.Any(s => x.Description.Contains(s)).ToList());
}

Upvotes: 0

Nick Kuznia
Nick Kuznia

Reputation: 1768

You could abuse Regex in this case (but performance would be terrible on large datasets, better to use native database searching), something like:

public ActionResult Search(string search_string)
{
    string regString = Regex.Replace(search_string.Trim(), @"[^A-Za-z0-9\s]", @"\$0"); //escape possible regex characters
    regString = Regex.Replace(regString, @"\s+", @"|"); //replace whitespace with "or" search operator
    regString = Regex.Replace(regString, @"[^\|]+", @"\b$0\b"); //optionally make words match whole words (can comment this out to allow partials)

    Regex regex = new Regex(regString, RegexOptions.IgnoreCase); //create regex and ignore character case

    return view(db.AttributesTable.Where(x => regex.IsMatch(x.Description)).ToList());
}

Upvotes: 0

Niyoko
Niyoko

Reputation: 7672

For very simple searches, you can use following code

var terms = search_string.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
IQueryable<Attributes> att = db.AttributesTable;

foreach(var term in terms)
{
    att = att.Where(x => x.Description.Contains(term));
}

return View(att.ToList());

It will return all rows that contains all words specified in search_string.


Edit

To return rows that contains ANY of the word in search_string you can build expression yourself. It's a little hard. but it's possible.

var terms = search_string.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);

var varExpr = Expression.Variable(typeof(YourClass), "x");

var strContainsMethodInfo = typeof(string).GetMethod("Contains");
var propInfo = typeof(YourClass).GetProperty("Description");

var falseExpr = (Expression) Expression.Constant(false);
var body = terms
    .Select(Expression.Constant)
    .Select(con => Expression.Call(Expression.Property(varExpr, propInfo), strContainsMethodInfo, con))
    .Aggregate(falseExpr, Expression.OrElse);

var lamb = (Expression<Func<YourClass, bool>>)Expression.Lambda(body, varExpr);
var att = db.AttributesTable
            .Where(lamb);

return View(att.ToList());

Change YourClass to your entity class i.e. Attribute or something.

Upvotes: 2

Raghu
Raghu

Reputation: 136

        string field = "{ apples, pears, bananas, grapes }";
        string input = "apple Banana Pears";
        List<string> result = null; 

        string[] inputs = input.ToLower().Split(' ');           
        foreach (var item in inputs)
        {
            if (field.ToLower().Contains(item)) result.Add(item);               
        }
        return result;
        //This will match even if input word is a substring in the field , which may not be a complete word in field.
        //e.g. banana is found in bananas in field. is it fine.

Upvotes: -1

OnurBulbul
OnurBulbul

Reputation: 431

You can use SqlMethods.dll. There exists a method named as "Like".

Upvotes: 0

Related Questions