Reputation: 85
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
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
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
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
.
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
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
Reputation: 431
You can use SqlMethods.dll. There exists a method named as "Like".
Upvotes: 0