Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V4.0 Filter Support #366

Open
wants to merge 41 commits into
base: release/4.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f92ca59
abstractions
nzdev Jul 30, 2023
774342b
reorder
nzdev Jul 30, 2023
8365d87
Revert "reorder"
nzdev Jul 30, 2023
14b33b4
wip
nzdev Jul 31, 2023
c6fca6c
push
nzdev Jul 31, 2023
36916df
LuceneFilter
nzdev Jul 31, 2023
4638f63
Wip
nzdev Jul 31, 2023
0a9fb58
WIP
nzdev Jul 31, 2023
76f2ae6
WIP
nzdev Jul 31, 2023
6d8926f
WIP
nzdev Jul 31, 2023
8ea66d7
WIP
nzdev Jul 31, 2023
7ec5b96
WIP
nzdev Jul 31, 2023
5d57262
Wip filter
nzdev Jul 31, 2023
f52f140
wip
nzdev Aug 2, 2023
739a710
merge
nzdev Aug 2, 2023
7f67b32
merge
nzdev Aug 2, 2023
f785ff5
WIP
nzdev Aug 2, 2023
0fc5191
Wip
nzdev Aug 2, 2023
8765ad7
wip
nzdev Aug 2, 2023
b175c94
wip
nzdev Aug 2, 2023
693b236
Merge branch 'release/4.0' of https://github.com/Shazwazza/Examine in…
nzdev Aug 18, 2023
4ce2198
test not
nzdev Aug 18, 2023
02573da
Range filter
nzdev Aug 18, 2023
42198f7
xdoc
nzdev Aug 18, 2023
80d796f
merge v4 beta1
nzdev Dec 7, 2023
e672962
Filter query support
nzdev Dec 7, 2023
02556ff
Nested Query Filter
nzdev Dec 7, 2023
ee23263
internal
nzdev Dec 7, 2023
7df1076
internal
nzdev Dec 7, 2023
b8c814a
tidy
nzdev Dec 7, 2023
5055af1
Fix dequeue
nzdev Dec 7, 2023
84edbd0
Filter chaining
nzdev Dec 7, 2023
e9bbc8e
Filter occurance support
nzdev Dec 7, 2023
be8426c
Remove IChainStart
nzdev Dec 7, 2023
85b09cb
Index float as single rather than a double
nzdev Dec 7, 2023
dd70636
float
nzdev Dec 7, 2023
b635740
Merge branch 'bugfix/single-float' of https://github.com/nzdev/Examin…
nzdev Dec 7, 2023
2334205
Filter tests
nzdev Dec 7, 2023
1761dc7
doc examples
nzdev Dec 7, 2023
d54bd4c
Test and docs for lucene Filter
nzdev Dec 7, 2023
0d69e07
Remove chaining support as it's removed in lucene 5
nzdev Dec 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 215 additions & 0 deletions docs/articles/filtering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
---
title: Filtering
permalink: /filtering
uid: filtering
order: 3
---
Filtering
===

_**Tip**: There are many examples of filtering in the [`FluentApiTests` source code](https://github.com/Shazwazza/Examine/blob/release/3.0/src/Examine.Test/Examine.Lucene/Search/FluentApiTests.cs) to use as examples/reference._

## Common

Obtain an instance of [`ISearcher`](xref:Examine.ISearcher) for the index to be searched from [`IExamineManager`](xref:Examine.IExamineManager).

### Terms and Phrases

When filtering on fields like in the example above you might want to search on more than one word/term. In Examine this can be done by simply adding more terms to the term filter.

### Term Filter

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that has "Hills" or "Rockyroad" or "Hollywood"
.WithFilter(
filter =>
{
filter.TermFilter(new FilterTerm("Address", "Hills Rockyroad Hollywood"));
})
.All()
.Execute();
```

### Terms Filter

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that has "Hills" or "Rockyroad" or "Hollywood"
.WithFilter(
filter =>
{
filter.TermsFilter(new[] {new FilterTerm("Address", "Hills"), new FilterTerm("Address", "Rockyroad"), new FilterTerm("Address", "Hollywood") });
})
.All()
.Execute();
```

### Term Prefix Filter

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that starts with "Hills"
.WithFilter(
filter =>
{
filter.TermPrefixFilter(new FilterTerm("Address", "Hills"));
})
.All()
.Execute();
```

## Range Filters

Range Filters allow one to match documents whose field(s) values are between the lower and upper bound specified by the Range Filter

### Int Range

Example:

```csharp
var searcher = myIndex.Searcher;
var query = searcher.CreateQuery();
query.WithFilter(
filter =>
{
filter.IntRangeFilter("SomeInt", 0, 100, minInclusive: true, maxInclusive: true);
}).All();
var results = query.Execute(QueryOptions.Default);
```

This will return results where the field `SomeInt` is within the range 0 - 100 (min value and max value included).

### Long Range

Example:

```csharp
var searcher = myIndex.Searcher;
var query = searcher.CreateQuery();
query.WithFilter(
filter =>
{
filter.LongRangeFilter("SomeLong", 0, 100, minInclusive: true, maxInclusive: true);
}).All();
var results = query.Execute(QueryOptions.Default);
```

This will return results where the field `SomeLong` is within the range 0 - 100 (min value and max value included).

### Float Range

Example:

```csharp
var searcher = myIndex.Searcher;
var query = searcher.CreateQuery();
query.WithFilter(
filter =>
{
filter.FloatRangeFilter("SomeFloat", 0f, 100f, minInclusive: true, maxInclusive: true);
}).All();
var results = query.Execute(QueryOptions.Default);
```

This will return results where the field `SomeFloat` is within the range 0 - 100 (min value and max value included).

### Double Range

Example:

```csharp
var searcher = myIndex.Searcher;
var query = searcher.CreateQuery();
query.WithFilter(
filter =>
{
filter.FloatRangeFilter("SomeDouble", 0.0, 100.0, minInclusive: true, maxInclusive: true);
}).All();
var results = query.Execute(QueryOptions.Default);
```

This will return results where the field `SomeDouble` is within the range 0 - 100 (min value and max value included).

## Booleans

### Or

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that start with "Hills" or "Valleys"
.WithFilter(
filter =>
{
filter.TermPrefixFilter(new FilterTerm("Address", "Hills"))
.OrFilter()
filter.TermPrefixFilter(new FilterTerm("Address", "Valleys"));
})
.All()
.Execute();
```

### And

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that has "Hills" and keyword "Examine"
.WithFilter(
filter =>
{
filter.TermFilter(new FilterTerm("Address", "Hills"))
.AndFilter()
filter.TermFilter(new FilterTerm("Keyword", "Examine"));
})
.All()
.Execute();
```

### Not

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that has "Hills" and keyword "Examine"
.WithFilter(
filter =>
{
filter.TermFilter(new FilterTerm("Address", "Hills"))
.NotFilter()
filter.TermFilter(new FilterTerm("Keyword", "Examine"));
})
.All()
.Execute();
```

### And Not

```csharp
var searcher = myIndex.Searcher;
var results = searcher.CreateQuery()
// Look for any addresses that has "Hills" and not keyword "Examine"
.WithFilter(
filter =>
{
filter.TermFilter(new FilterTerm("Address", "Hills"))
.AndNotFilter(innerFilter => innerFilter.TermFilter(new FilterTerm("Keyword", "Examine")));
})
.All()
.Execute();
```

### Custom lucene filter

```csharp
var searcher = indexer.Searcher;
var query = searcher.CreateQuery();

var query = (LuceneSearchQuery)query.NativeQuery("hello:world").And(); // Make query ready for extending
query.LuceneFilter(new TermFilter(new Term("nodeTypeAlias", "CWS_Home"))); // Add the raw lucene query
var results = query.Execute();
```
2 changes: 2 additions & 0 deletions docs/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
href: indexing.md
- name: Searching
href: searching.md
- name: Filtering
href: filtering.md
- name: Sorting
href: sorting.md
- name: Paging
Expand Down
8 changes: 7 additions & 1 deletion src/Examine.Core/FieldDefinitionTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
public const string Integer = "int";

/// <summary>
/// Will be indexed as a float
/// Will be indexed as a single
/// </summary>
public const string Float = "float";

/// <summary>
/// Will be indexed as a single
/// </summary>
[Obsolete("To remove in Examine V5. Use Float")]
public const string Single = "single";

Check warning on line 24 in src/Examine.Core/FieldDefinitionTypes.cs

View workflow job for this annotation

GitHub Actions / build

Check warning on line 24 in src/Examine.Core/FieldDefinitionTypes.cs

View workflow job for this annotation

GitHub Actions / build


/// <summary>
/// Will be indexed as a double
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions src/Examine.Core/Search/FilterTerm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace Examine.Search
{
/// <summary>
/// Term
/// </summary>
public struct FilterTerm

Check warning on line 6 in src/Examine.Core/Search/FilterTerm.cs

View workflow job for this annotation

GitHub Actions / build

Check warning on line 6 in src/Examine.Core/Search/FilterTerm.cs

View workflow job for this annotation

GitHub Actions / build

Symbol 'implicit constructor for 'FilterTerm'' is not part of the declared public API (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check warning on line 6 in src/Examine.Core/Search/FilterTerm.cs

View workflow job for this annotation

GitHub Actions / build

{
/// <summary>
/// Name of the Field
/// </summary>
public string FieldName { get; }

/// <summary>
/// Value of the Term
/// </summary>
public string FieldValue { get; }

/// <summary>
/// Constructor
/// </summary>
/// <param name="fieldName">Name of the Field</param>
/// <param name="fieldValue">Value of the Term</param>
public FilterTerm(string fieldName, string fieldValue)
{
FieldName = fieldName;
FieldValue = fieldValue;
}

}
}
49 changes: 49 additions & 0 deletions src/Examine.Core/Search/IBooleanFilterOperation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;

namespace Examine.Search
{
public interface IBooleanFilterOperation

Check warning on line 5 in src/Examine.Core/Search/IBooleanFilterOperation.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'IBooleanFilterOperation'

Check warning on line 5 in src/Examine.Core/Search/IBooleanFilterOperation.cs

View workflow job for this annotation

GitHub Actions / build

Symbol 'IBooleanFilterOperation' is not part of the declared public API (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)

Check warning on line 5 in src/Examine.Core/Search/IBooleanFilterOperation.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'IBooleanFilterOperation'

Check warning on line 5 in src/Examine.Core/Search/IBooleanFilterOperation.cs

View workflow job for this annotation

GitHub Actions / build

Symbol 'IBooleanFilterOperation' is not part of the declared public API (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
{
/// <summary>
/// Sets the next operation to be AND
/// </summary>
/// <returns></returns>
IFilter AndFilter();

/// <summary>
/// Adds the nested filter
/// </summary>
/// <param name="inner"></param>
/// <param name="defaultOp"></param>
/// <returns></returns>
IBooleanFilterOperation AndFilter(Func<INestedFilter, INestedBooleanFilterOperation> inner, BooleanOperation defaultOp = BooleanOperation.And);

/// <summary>
/// Sets the next operation to be OR
/// </summary>
/// <returns></returns>
IFilter OrFilter();

/// <summary>
/// Adds the nested filter
/// </summary>
/// <param name="inner"></param>
/// <param name="defaultOp"></param>
/// <returns></returns>
IBooleanFilterOperation OrFilter(Func<INestedFilter, INestedBooleanFilterOperation> inner, BooleanOperation defaultOp = BooleanOperation.And);

/// <summary>
/// Sets the next operation to be NOT
/// </summary>
/// <returns></returns>
IFilter NotFilter();

/// <summary>
/// Adds the nested filter
/// </summary>
/// <param name="inner"></param>
/// <param name="defaultOp"></param>
/// <returns></returns>
IBooleanFilterOperation AndNotFilter(Func<INestedFilter, INestedBooleanFilterOperation> inner, BooleanOperation defaultOp = BooleanOperation.And);
}
}
Loading
Loading