SearchExtensions: Search strings with the new Fluent API

by John Nye

05 Mar
2014

I am pleased to announce a NEW Fluent Search API for SearchExtensions nuget package

As of version 0.5, SearchExtensions now has a fluent API enabling a more control over your queries as well as making them easy to read. Here are the changes:

IQueryable Searching

Because of the Fluent API update, we are now able to offer up some additional methods to search.

Methods

Search methods available to IQueryable data are:

  • Containing - target property contains search term(s)
  • IsEqual - target property equals search term(s)
  • StartsWith - target property starts with search term(s)

Setup

Previous functionality of searching against any number of properties is still supported. Now however you only define the properties you want to perform a search against as part of the setup action.

using NinjaNye.SearchExtensions.Fluent;
//...

var result = data.Search(x => x.Name, x => x.Description)

Defining more than one property states that you want results that are matched within any of the properties.

Once we have identified the properties we wish to search we can start to perform some search actions

Performing a Containing search

Return all records where the Name property contains "search"

var result = data.Search(x => x.Name).Containing("search");

Return all records where the Name property OR the Description property contains "search":

var result = data.Search(x => x.Name, x => x.Description).Containing("search");

Return all records where the Name property OR the Description property contains "search" OR "term":

var result = data.Search(x => x.Name, x => x.Description).Containing("search", "term");

Performing a IsEqual search

Return all records where the Name property equals "search"

var result = data.Search(x => x.Name).IsEqual("search");

Return all records where the Name property OR the Description property equals "search":

var result = data.Search(x => x.Name, x => x.Description).IsEqual("search");

Return all records where the Name property OR the Description property equals "search" OR "term":

var result = data.Search(x => x.Name, x => x.Description).IsEqual("search", "term");

Performing a StartsWith search

Return all records where the Name property starts with "search"

var result = data.Search(x => x.Name).StartsWith("search");

Return all records where the Name property OR the Description property starts with "search":

var result = data.Search(x => x.Name, x => x.Description).StartsWith("search");

Return all records where the Name property OR the Description property starts with "search" OR "term":

var result = data.Search(x => x.Name, x => x.Description).StartsWith("search", "term");

Combining instructions

With the latest version of SearchExtensions you can also combine search actions. For instance

Search where a Name property starts with "john AND is containing "nye":

var result = queryableData.Search(x => x.Name)
                          .StartsWith("john")
                          .Containing("nye");

The ability to pass multiple search terms to any of the action methods still remains. The following returns any record where the Name property OR the Title property starts with either "john" or "web" AND contains "nye" or "developer"

var result = queryableData.Search(x => x.Name, x.Title)   
                          // that starts with "john" OR "web"
                          .StartsWith("john", "web")
                          // and contains ins "nye" OR "developer"
                          .Containing("nye", "developer")

IEnumerable (in memory) Searches

The fluent API has also been extended to support IEnumerable collections (not just IQueryable).

This means you can now perform all of the above searches on in memory collections should you need to. The important thing to remember when performing an in memory search is to set the culture to the type of string comparison you wish to perform. If SetCulture is not specified, StringComparison.CurrentCulture is used.

How to: Performing IEnumerable searches

These methods are identical to that of the IQueryable methods except the comparison functions have an additional overload that takes a string comparison.

IEnumerable extensions also has an additional method named EndsWith.

var result = enumerableData.Search(x => x.Description)
                           // Set culture for comparison
                           .SetCulture(StringComparison.OrdinalIgnoreCase)
                           .StartsWith("abc")
                           .EndsWith("xyz")
                           .Containing("mno");

It is also possible to set the comparison multiple times

var result = enumerableData.Search(x => x.Description)
                           .SetCulture(StringComparison.OrdinalIgnoreCase)
                           .StartsWith("abc")  // Uses OrdinalIgnoreCase
                           .SetCulture(StringComparison.Ordinal)
                           .EndsWith("xyz")    // Uses Ordinal
                           .SetCulture(StringComparison.CurrentCulture)
                           .Containing("mno"); //Uses CurrentCulture

I hope you all enjoy this latest release. This package is still under development so I welcome any feedback you have.


Installation

To install SearchExtensions you can simply write the following in you Package Manager Console

PM> Install-Package NinjaNye.SearchExtensions

Comments 5

gas says: 2888 days ago

I see that its possible to search something starting with "x" and containing "X".. but... Is it possible to do a search by equal OR containing ?? For example equals "X" or containing "Y".

John says: 2855 days ago

Hi Gas,

The feature is not directly supported but you could do something like the following to achieve what you are after:

var equalsX = context.Search(x => x.SrtringOne).EqualTo("X");
var containsY = context.Search(x => x.StringOne).Containing("Y");

The above effectively performs 2 searches, the for records equal to "X" and the second for records containing "Y".


This is not the first time a request like this has come in so maybe I could introduce something like the following that turns and AND operator into and OR operator:

var result = context.Search(x => x.StringOne)
                    .EqualTo("X")
                    .Or().Containing("Y");

The Or prefix could effectively turn any of the filter methods into an OR statement.

Thanks for getting in touch

Tom says: 2674 days ago

I was using predicate builder and was doing searches on joined data.

Example..

 var predicateF = PredicateBuilder.New<PurchaseOrder>()
                        .Or(f => f.Vendor.Name.Contains(parms.searchText))
                        .Or(f => f.LineItems.Any(y => y.StrainName.Contains(parms.searchText)))
                        .Or(f => f.LineItems.Any(y => y.ToComplianceId.Contains(parms.searchText)))
                        .Or(f => f.LineItems.Any(y => y.ComplianceId.Contains(parms.searchText)))
                        .Or(f => f.Manifest.ComplianceId.Contains(parms.searchText))

Is this possible?

Fawaz says: 2296 days ago

Hi John, thanks for this excellent nuget package. I wanted to check if there is a possibility to search two string and uniquely find a record. What I mean is that for instance if I have a row in my table with name 'fawaz' and postcode 'sw17' I want to only bring this row and not the others where others where the name of postcode matches. Is that possible with the current version? How does it perform on a table record of around 200,000 records?

Cheers Fawaz

John says: 2280 days ago

Hi Fawaz,

If you want to achieve an AND search, you can do something like the following:

var result = queryableData.Search(x => x.Name).EqualTo("fawaz")
                          .Search(x => x.Postcode).EqualTo("sw17");

This will perform a search and return all records that have both these values set

Hope this helps

Leave a message...

18 Apr
2024