![]() |
VOOZH | about |
dotnet add package NinjaNye.SearchExtensions --version 4.0.1
NuGet\Install-Package NinjaNye.SearchExtensions -Version 4.0.1
<PackageReference Include="NinjaNye.SearchExtensions" Version="4.0.1" />
<PackageVersion Include="NinjaNye.SearchExtensions" Version="4.0.1" />Directory.Packages.props
<PackageReference Include="NinjaNye.SearchExtensions" />Project file
paket add NinjaNye.SearchExtensions --version 4.0.1
#r "nuget: NinjaNye.SearchExtensions, 4.0.1"
#:package NinjaNye.SearchExtensions@4.0.1
#addin nuget:?package=NinjaNye.SearchExtensions&version=4.0.1Install as a Cake Addin
#tool nuget:?package=NinjaNye.SearchExtensions&version=4.0.1Install as a Cake Tool
SearchExtensions is a library of IQueryable and IEnumerable extension methods to perform searching. More information on these packages and it's use can be found by, visiting my blog.
This project represents the source code for the following 3 nuget packages:
IEnumerable and IQueryable collections.IEnumerable collections.IEnumerable collections.As of version 3.0 Soundex and Levenshtein support has been migrated into their own respective packages (above). All functionality still remains. If you are currently using Levensthein or Soundex functionlity in version 2.2 or lower, please upgrade to you the dedicated package.
The IQueryable extension methods build expression trees based on your command chain and then sends this request to the data provider when required. This means that your data provider is restricting the records that are brought into memory instead of having all records brought into, and filtered, in memory.
Search methods available to IQueryable data are:
Containing - target property contains search term or termsIsEqual - target property equals search term or termsStartsWith - target property starts with search term or termsContaining searchesSearch for a single search term within a single property
var result = queryableData.Search(x => x.Property1)
.Containing("searchTerm");
Search for a single search term within multiple properties
var result = queryableData.Search(x => x.Property1,
x => x.Property2,
x => x.Property3)
.Containing("searchTerm");
Search for multiple search terms within a single property
var result = queryableData.Search(x => x.Property1)
.Containing("search", "term");
Search for multiple search terms within multiple properties
var result = queryableData.Search(x => x.Property1,
x => x.Property2,
x => x.Property3)
.Containing("searchTerm1",
"searchTerm2",
"searchTerm3");
Containing AND searchesSearch where a single property contains a single search term
AND a another property contains a single search term
var result = queryableData.Search(x => x.Property1)
.Containing("searchTerm1")
.Search(x => x.Property1)
.Containing("searchTerm2");
Search where a single search term exists within in Property1 OR Property2
AND single search term exists within in Property3 OR Property4
var result = queryableData.Search(x => x.Property1, x => x.Property2)
.Containing("searchTerm")
.Search(x => x.Property3, x => x.Property4)
.Containing("searchTerm");
Search where a single search term exists in Property1 OR Property2
AND any of the multiple search terms exist within a single property
var result = queryableData.Search(x => x.Property1, x => x.Property2)
.Containing("searchTerm")
.Search(x => x.Property3)
.Containing("another", "term");
IsEqual searchesSearch where a single property equals a single search term
var result = queryableData.Search(x => x.Property1)
.IsEqual("searchTerm");
Search where any one of multiple properties is equal to a single search term
var result = queryableData.Search(x => x.Property1,
x => x.Property2,
x => x.Property3)
.IsEqual("searchTerm");
Search where a single property is equal to any one of multiple search terms
var result = queryableData.Search(x => x.Property1)
.IsEqual("search", "term");
Search where any one of multiple properties is equal to any one of multiple search terms
var result = queryableData.Search(x => x.Property1,
x => x.Property2,
x => x.Property3)
.IsEqual("searchTerm1",
"searchTerm2",
"searchTerm3");
StartsWith searchesSearch where a single property starts with a single search term
var result = queryableData.Search(x => x.Property1)
.StartsWith("searchTerm");
Search where any one of multiple properties starts with to a single search term
var result = queryableData.Search(x => x.Property1,
x => x.Property2,
x => x.Property3)
.StartsWith("searchTerm");
Search where a single property starts with any one of multiple search terms
var result = queryableData.Search(x => x.Property1)
.StartsWith("search", "term");
Search where any one of multiple properties starts with any one of multiple search terms
var result = queryableData.Search(x => x.Property1,
x => x.Property2,
x => x.Property3)
.StartsWith("searchTerm1",
"searchTerm2",
"searchTerm3");
With the latest version of SearchExtensions you can also combine search actions. For instance
Search where a single property starts with a single search term AND containing a single search term
var result = queryableData.Search(x => x.Property1)
.StartsWith("abc")
.Containing("mno");
The ability to pass multiple search terms to any of the action methods still remains:
var result = queryableData.Search(x => x.Property1, x => x.Property2)
// that starts with "abc" OR "ninja"
.StartsWith("abc", "ninja")
// and contains "xyz" OR "extensions"
.Containing("xyz", "extensions")
SearchExtensions has also been extended to support IEnumerable collections.
This means you can now perform all of the above searches on in memory collections should you need to.
Currently IEnumerable searching has more features available to it than IQueryable, namely EndsWith and SetCulture
SetCulture - Sets the string comparison culture with which to perform searchesContaining - target property contains search term or termsIsEqual - target property equals search term or termsStartsWith - target property starts with search term or termsEndsWith - target property ends with search term or termsThe 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.
These methods are identical to that of the IQueryable methods.
var result = enumerableData.Search(x => x.Property1)
.SetCulture(StringComparison.OrdinalIgnoreCase) // Set culture for comparison
.StartsWith("abc")
.EndsWith("xyz")
.Containing("mno");
It is also possible to switch the StringComparison culture context multiple times
var result = enumerableData.Search(x => x.Property1)
.SetCulture(StringComparison.OrdinalIgnoreCase)
.StartsWith("abc") // Uses OrdinalIgnoreCase
.SetCulture(StringComparison.Ordinal)
.EndsWith("xyz") // Uses Ordinal
.SetCulture(StringComparison.CurrentCulture)
.Containing("mno"); //Uses CurrentCulture
Another feature of the fluent api across both IQueryable and IEnumerable collections is the ToRanked() method.
As well as returning the matched items, a Ranked Search also returns a hit count for each item in the form of an IRanked<T> result. This enables you to order by hit count to retrieve the most relevant search results.
IRanked<T> resultAn IRanked<T> result is simply defined as follows:
public interface IRanked<out T>
{
int Hits { get; }
T Item { get; }
}
This is returned using the ToRanked() method:
RankedSearch for a single search term within a single property
var result = queryableData.Search(x => x.Property1)
.Containing("searchTerm")
.ToRanked();
RankedSearch for a single search term within multiple properties
var result = queryableData.Search(x => x.Property1, x => x.Property2, x => x.Property3)
.Containing("searchTerm")
.ToRanked();
RankedSearch for multiple search terms within a single property
var result = queryableData.Search(x => x.Property1)
.Containing("searchTerm1", "searchTerm2", "searchTerm3")
.ToRanked();
RankedSearch for multiple search terms within multiple properties
var result = queryableData.Search(x => x.Property1, x => x.Property2)
.Containing("searchTerm1", "searchTerm2", "searchTerm3")
.ToRanked();
Using ranked search you can now easily order your search results by the most relevant. This following example assumes we have a list of User which has FirstName, LastName and MiddleName string properties. In this example we want to match on those with "John" in their name and retrieve the top 10 results.
var result = context.Users.Search(x => x.FirstName, x => x.LastName, x.MiddleName)
.Containing("John")
.ToRanked()
.OrderByDescending(r => r.Hits) // Order by Hits property of IRanked<User>
.Take(10);
We can also mix it up with the other fluent API methods
var result = context.Users.Search(x => x.FirstName, x => x.LastName, x => x.MiddleName)
.StartsWith("john")
.Containing("nye")
.ToRanked()
.OrderByDescending(r => r.Hits) // Order by Hits property of IRanked<User>
.Take(10);
Be aware that the ToRanked() method uses the search terms of the Containing() method combined with the properties to search to build its hit count. The fluent ToRanked() method also means the old RankedSearch method is now depreciated. It still lives in the code but will soon be removed so please update your code to use the fluent api.
NinjaNye.SearchExtensions.Soundex supports converting and searching for words that sound like a given word.
Soundex searchesReturning records that 'sound like' "test" using the Soundex algorythm:
Search where a single property sounds like a single search term
var result = data.SoundexOf(x => x.Property1).Matching("test")
Search where a any of multiple properties sounds like a single search term
var result = data.SoundexOf(x => x.Property1, x => x.PropertyTwo)
.Matching("test")
Search where a single property sounds like any one of multiple search terms
var result = data.SoundexOf(x => x.Property1).Matching("test", "another")
Search where a any of multiple properties sounds like any of multiple search terms
var result = data.SoundexOf(x => x.Property1, x => x.PropertyTwo)
.Matching("test", "another")
ReverseSoundex searchesAll the abouve soundex axamples can be performed using the Reverse Soundex algorythm.
Simply substitute in the ReverseSoundexOf() method. For example:
Search where a single property sounds like a single search term
var result = data.ReverseSoundexOf(x => x.Property1).Matching("test")
Search where a any of multiple properties sounds like a single search term
var result = data.ReverseSoundexOf(x => x.Property1, x => x.PropertyTwo)
.Matching("test")
The above
SoundexOfandReverseSoundexOfmethods can also be applied toIQueryabledata. ForIQueryablewe reduce the amount of records returned from the data source as much as possible but be aware that the soundex searching is performed on the in memory collection.
For more information about the Soundex search functionality, soundex search performance, and how it has been integrated with IQueryable, please visit http://jnye.co/soundex
If you have any new feature requests, questions, or comments, please get in touch, either, via my website, twitter or preferrably raise an issue in this github repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp1.0 netcoreapp1.0 was computed. netcoreapp1.1 netcoreapp1.1 was computed. netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard1.0 netstandard1.0 is compatible. netstandard1.1 netstandard1.1 was computed. netstandard1.2 netstandard1.2 was computed. netstandard1.3 netstandard1.3 was computed. netstandard1.4 netstandard1.4 was computed. netstandard1.5 netstandard1.5 was computed. netstandard1.6 netstandard1.6 was computed. netstandard2.0 netstandard2.0 was computed. netstandard2.1 netstandard2.1 is compatible. |
| .NET Framework | net45 net45 was computed. net451 net451 was computed. net452 net452 was computed. net46 net46 was computed. net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 is compatible. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen30 tizen30 was computed. tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Universal Windows Platform | uap uap was computed. uap10.0 uap10.0 was computed. |
| Windows Phone | wp8 wp8 was computed. wp81 wp81 was computed. wpa81 wpa81 was computed. |
| Windows Store | netcore netcore was computed. netcore45 netcore45 was computed. netcore451 netcore451 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on NinjaNye.SearchExtensions:
| Package | Downloads |
|---|---|
|
NinjaNye.SearchExtensions.Levenshtein
A collection of extension methods to IQueryable and IEnumerable that enable easy and performance Levenshtein searches |
|
|
NinjaNye.SearchExtensions.Soundex
A collection of extension methods to IQueryable and IEnumerable that enable easy and performance Soundex searches |
|
|
LShared.Frameworks
Package Description |
|
|
NiuX.Common
csharp common, utils, helpers, tools etc. |
|
|
LevelB.Arch.Core
LevelB.Arch.Core |
Showing the top 1 popular GitHub repositories that depend on NinjaNye.SearchExtensions:
| Repository | Stars |
|---|---|
|
SteamAutoCracks/Steam-auto-crack
Steam Game Automatic Cracker
|
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.1 | 340,020 | 7/5/2024 |
| 4.0.0.3 | 892 | 7/3/2024 |
| 4.0.0.2 | 366 | 7/3/2024 |
| 4.0.0.1 | 369 | 7/3/2024 |
| 4.0.0 | 3,147 | 7/3/2024 |
| 3.0.1 | 1,537,828 | 6/17/2019 |
| 3.0.0 | 23,962 | 2/4/2019 |
| 2.2.0 | 98,052 | 7/25/2017 |
| 2.1.0 | 16,873 | 4/1/2017 |
| 2.0.6149.33145 | 57,662 | 11/1/2016 |
| 1.8.6091.39511 | 38,525 | 9/4/2016 |
| 1.8.6017.41438 | 32,857 | 6/22/2016 |
| 1.8.5964.15074 | 5,444 | 4/30/2016 |
| 1.7.5798.38367 | 11,417 | 11/16/2015 |
| 1.7.5787.330 | 2,204 | 11/5/2015 |
| 1.7.5772.14200 | 2,223 | 10/21/2015 |
| 1.6.5770.26922 | 2,205 | 10/19/2015 |
| 1.6.5730.33279 | 2,494 | 9/9/2015 |
| 1.6.5728.37462 | 2,219 | 9/7/2015 |
| 1.6.5728.32066 | 2,172 | 9/7/2015 |
NinjaNye.SearchExtensions library. Now built with dotnet core support (netstandard 1.0)