diff --git a/.github/workflows/docfx-gh-pages.yml b/.github/workflows/docfx-gh-pages.yml
index 1321b4ba9..9ec09b6d9 100644
--- a/.github/workflows/docfx-gh-pages.yml
+++ b/.github/workflows/docfx-gh-pages.yml
@@ -33,7 +33,7 @@ jobs:
- name: Setup Github Pages
uses: actions/configure-pages@v3
- name: Build DocFX Site
- uses: VakuWare/docfx-pdf-action@v1.4.0
+ uses: nunit/docfx-action@v2.10.0
with:
args: docs/docfx.json
- name: Upload docfx built site artifact
diff --git a/docs/api/index.md b/docs/api/index.md
index 6b256ce8a..680c23fcc 100644
--- a/docs/api/index.md
+++ b/docs/api/index.md
@@ -1,7 +1,7 @@
---
uid: apidocsindex
---
-# Examine V3 API Documentation
+# Examine V4 API Documentation
API documentation is automatically generated.
diff --git a/docs/articles/configuration.md b/docs/articles/configuration.md
index 8873dd988..ff2d43170 100644
--- a/docs/articles/configuration.md
+++ b/docs/articles/configuration.md
@@ -1,5 +1,4 @@
---
-layout: page
title: Configuration
permalink: /configuration
uid: configuration
diff --git a/docs/articles/indexing.md b/docs/articles/indexing.md
index 946328376..7ad7ca846 100644
--- a/docs/articles/indexing.md
+++ b/docs/articles/indexing.md
@@ -1,5 +1,4 @@
---
-layout: page
title: Indexing
permalink: /indexing
uid: indexing
diff --git a/docs/articles/searching.md b/docs/articles/searching.md
index 18dd2d5c1..6b2fd0250 100644
--- a/docs/articles/searching.md
+++ b/docs/articles/searching.md
@@ -1,5 +1,4 @@
---
-layout: page
title: Searching
permalink: /searching
uid: searching
diff --git a/docs/articles/sorting.md b/docs/articles/sorting.md
index 66d062ee1..4baf84adc 100644
--- a/docs/articles/sorting.md
+++ b/docs/articles/sorting.md
@@ -1,5 +1,4 @@
---
-layout: page
title: Sorting
permalink: /sorting
uid: sorting
diff --git a/docs/articles/suggesting.md b/docs/articles/suggesting.md
new file mode 100644
index 000000000..bddf413ed
--- /dev/null
+++ b/docs/articles/suggesting.md
@@ -0,0 +1,87 @@
+---
+layout: page
+title: Suggesting
+permalink: /suggesting
+ref: suggesting
+order: 2
+---
+Suggesting and Spell Checking
+===
+
+_**Tip**: There are many examples of searching in the [`SuggesterApiTests` source code](https://github.com/Shazwazza/Examine/blob/master/src/Examine.Test/Lucene/Suggest/SuggesterApiTests.cs) to use as examples/reference._
+
+
+## Registering Suggesters
+
+On the index to register the Suggesters, create a SuggesterDefinitionCollection and set it on IndexOptions.SuggesterDefinitions
+
+Examples for suggesting or spellchecking based on the "fullName" index field.
+
+```cs
+ var suggesters = new SuggesterDefinitionCollection();
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.AnalyzingInfixSuggester, ExamineLuceneSuggesterNames.AnalyzingInfixSuggester, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.AnalyzingSuggester, ExamineLuceneSuggesterNames.AnalyzingSuggester, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker, ExamineLuceneSuggesterNames.DirectSpellChecker, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker_LevensteinDistance, ExamineLuceneSuggesterNames.DirectSpellChecker_LevensteinDistance, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker_JaroWinklerDistance, ExamineLuceneSuggesterNames.DirectSpellChecker_JaroWinklerDistance, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker_NGramDistance, ExamineLuceneSuggesterNames.DirectSpellChecker_NGramDistance, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.FuzzySuggester, ExamineLuceneSuggesterNames.FuzzySuggester, new string[] { "fullName" }));
+```
+
+## Suggester API
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new SuggestionOptions(5,ExamineLuceneSuggesterNames.AnalyzingSuggester));
+```
+
+This code will run a suggestion for the input text "Sam", returning up to 5 suggestions.
+
+## Lucene Suggesters
+
+To generate suggestions for input text, retreive the ISuggester from the index IIndex.Suggester.
+
+### Analyzing Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.AnalyzingInfixSuggester));
+```
+
+This code will run a suggestion for the input text "Sam", returning up to 5 suggestions, and will highlight the result text which matches the input text..
+
+### Analyzing Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.AnalyzingSuggester));
+```
+
+This code will run a suggestion for the input text "Sam", returning up to 5 suggestions.
+
+### Fuzzy Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.FuzzySuggester));
+```
+
+This code will run a Fuzzy suggestion for the input text "Sam", returning up to 5 suggestions.
+
+## Lucene Spellcheckers
+
+To generate spellchecker suggestions for input text, retreive the ISuggester from the index IIndex.Suggester.
+
+### Direct SpellChecker Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.DirectSpellChecker));
+```
+
+This code will run a spellchecker suggestion for the input text "Sam" returning up to 5 suggestions.
diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml
index 2c385e520..3b84d20d2 100644
--- a/docs/articles/toc.yml
+++ b/docs/articles/toc.yml
@@ -7,4 +7,8 @@
- name: Sorting
href: sorting.md
- name: Paging
- href: sorting.md#paging-and-limiting-results
\ No newline at end of file
+ href: sorting.md#paging-and-limiting-results
+- name: Suggesters
+ href: suggesting.md
+- name: Spellchecking
+ href: suggesting.md#lucene-spellcheckers
\ No newline at end of file
diff --git a/docs/developerguides/buildtest.md b/docs/developerguides/buildtest.md
index 7659e04cd..bdf2f5395 100644
--- a/docs/developerguides/buildtest.md
+++ b/docs/developerguides/buildtest.md
@@ -1,5 +1,4 @@
---
-layout: page
title: Build and Test
permalink: /devbuildtest
uid: devbuildtest
diff --git a/docs/developerguides/codestructure.md b/docs/developerguides/codestructure.md
index 31198efe8..cf04cd18a 100644
--- a/docs/developerguides/codestructure.md
+++ b/docs/developerguides/codestructure.md
@@ -1,9 +1,8 @@
---
-layout: page
title: Code Structure
permalink: /devcodestructure
uid: devcodestructure
-order: 1
+order: 2
---
Code Structure
diff --git a/docs/developerguides/docsite.md b/docs/developerguides/docsite.md
index 782a68199..683160466 100644
--- a/docs/developerguides/docsite.md
+++ b/docs/developerguides/docsite.md
@@ -1,9 +1,8 @@
---
-layout: page
title: Documentation Site
permalink: /devdocsite
uid: devdocsite
-order: 1
+order: 3
---
Documentation Site
@@ -16,7 +15,7 @@ The easiest way to get started is to edit an existing page by clicking the Impro
## Building documentation
-1. Download [docfx](https://github.com/dotnet/docfx/releases).
+1. Install [docfx](https://github.com/dotnet/docfx/releases) dotnet tool update -g docfx.
2. Unzip the release and add the folder to your system path variables.
3. Open a terminal, for example PowerShell or the VS Code terminal.
4. Change directory to /docs
diff --git a/docs/developerguides/roadmap.md b/docs/developerguides/roadmap.md
index b177be593..a9df191b6 100644
--- a/docs/developerguides/roadmap.md
+++ b/docs/developerguides/roadmap.md
@@ -1,9 +1,8 @@
---
-layout: page
title: Roadmap
permalink: /devroadmap
uid: devroadmap
-order: 1
+order: 4
---
Examine.Lucene Roadmap
@@ -13,8 +12,6 @@ This page covers the roadmap for the core Examine abstractions and the Examine.L
## Ongoing and future work
-- [ ] [Facet Deep Paging](https://github.com/Shazwazza/Examine/pull/321)
-- [ ] [Hierarchical Faceting API (Taxonomy)](https://github.com/Shazwazza/Examine/pull/323)
- [ ] [Suggestions API and Spellchecking API](https://github.com/Shazwazza/Examine/pull/326)
- [ ] [Similarity API (BM25)](https://github.com/Shazwazza/Examine/pull/327)
- [ ] [GeoSpatial API](https://github.com/Shazwazza/Examine/pull/328)
@@ -22,6 +19,8 @@ This page covers the roadmap for the core Examine abstractions and the Examine.L
## Past and completed work
+- [x] [Facet Deep Paging](https://github.com/Shazwazza/Examine/pull/321)
+- [x] [Hierarchical Faceting API (Taxonomy)](https://github.com/Shazwazza/Examine/pull/323)
- [x] [Nullable Support](https://github.com/Shazwazza/Examine/pull/313)
- [x] [Faceting API (SortedDocValues)](https://github.com/Shazwazza/Examine/pull/311)
- [x] [Docfx website](https://github.com/Shazwazza/Examine/pull/322)
@@ -29,5 +28,11 @@ This page covers the roadmap for the core Examine abstractions and the Examine.L
## Release Notes
-### Examine 3.1
-[Examine 3.1 Release Notes](https://github.com/Shazwazza/Examine/releases/tag/v3.1.0)
\ No newline at end of file
+### Examine 4.0.0 beta 1
+[Examine 4.0.0 beta 1 Release Notes](https://github.com/Shazwazza/Examine/releases/tag/v4.0.0-beta.1)
+
+### Examine v3.2.0 beta 9
+[Examine v3.2.0 beta 9 Release Notes](https://github.com/Shazwazza/Examine/releases/tag/v3.2.0-beta.9)
+
+### Examine 3.1.0
+[Examine 3.1.0 Release Notes](https://github.com/Shazwazza/Examine/releases/tag/v3.1.0)
\ No newline at end of file
diff --git a/docs/docfx.json b/docs/docfx.json
index 445db277a..194bb9328 100644
--- a/docs/docfx.json
+++ b/docs/docfx.json
@@ -66,8 +66,14 @@
"fileMetadataFiles": [],
"template": [
"default",
- "templates/material"
+ "modern",
+ "templates/examinemodern"
],
+ "sitemap": {
+ "baseUrl": "https://shazwazza.github.io/Examine",
+ "priority": 0.1,
+ "changefreq": "monthly"
+ },
"postProcessors": ["ExtractSearchIndex"],
"markdownEngineName": "markdig",
"noLangKeyword": false,
@@ -76,6 +82,7 @@
"disableGitFeatures": false,
"globalMetadata": {
"_appTitle": "Examine",
+ "_appName": "Examine",
"_appFooter": "Examine",
"_enableSearch": true,
"_gitContribute": {
@@ -85,6 +92,8 @@
},
"_appLogoPath": "images/headerlogo.png",
"_appFaviconPath": "images/favicon.ico"
+ },
+ "fileMetadata": {
}
}
}
diff --git a/docs/docs-v1-v2/configuration.md b/docs/docs-v1-v2/configuration.md
index 70b09967e..ad8c4a897 100644
--- a/docs/docs-v1-v2/configuration.md
+++ b/docs/docs-v1-v2/configuration.md
@@ -1,5 +1,4 @@
---
-layout: page
title: V1/V2 Configuration
permalink: /configuration
uid: v2configuration
diff --git a/docs/docs-v1-v2/indexing.md b/docs/docs-v1-v2/indexing.md
index b439a0749..4387c161a 100644
--- a/docs/docs-v1-v2/indexing.md
+++ b/docs/docs-v1-v2/indexing.md
@@ -1,5 +1,4 @@
---
-layout: page
title: V1/V2 Indexing
permalink: /indexing
uid: v2indexing
diff --git a/docs/docs-v1-v2/searching.md b/docs/docs-v1-v2/searching.md
index bca9a0a37..2905d7804 100644
--- a/docs/docs-v1-v2/searching.md
+++ b/docs/docs-v1-v2/searching.md
@@ -1,5 +1,4 @@
---
-layout: page
title: V1/V2 Searching
permalink: /searching
uid: v2searching
diff --git a/docs/docs-v1-v2/sorting.md b/docs/docs-v1-v2/sorting.md
index 9382d79cc..4d21aa7de 100644
--- a/docs/docs-v1-v2/sorting.md
+++ b/docs/docs-v1-v2/sorting.md
@@ -1,5 +1,4 @@
---
-layout: page
title: V1/V2 Sorting
permalink: /sorting
uid: v2sorting
diff --git a/docs/index.md b/docs/index.md
index ef03772e4..f55119ebb 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -36,6 +36,7 @@ Releases are available [here](https://github.com/Shazwazza/Examine/releases) and
| Examine Version | .NET |
| --------------- | ---- |
+| V4 | .NET Standard 2.0 |
| V3 | .NET Standard 2.0 |
| V2 | .NET Standard 2.0 |
| V1 | .NET Framework 4.5.2 |
@@ -47,7 +48,7 @@ Releases are available [here](https://github.com/Shazwazza/Examine/releases) and
1. Install
```powershell
- > dotnet add package Examine --version 3.0.1
+ > dotnet add package Examine --version 4.0.0-beta1
```
1. Configure Services and create an index
diff --git a/docs/suggesting.md b/docs/suggesting.md
new file mode 100644
index 000000000..f25dade17
--- /dev/null
+++ b/docs/suggesting.md
@@ -0,0 +1,83 @@
+---
+layout: page
+title: Suggesting
+permalink: /suggesting
+ref: suggesting
+order: 2
+---
+Suggesting and Spell Checking
+===
+
+_**Tip**: There are many examples of searching in the [`SuggesterApiTests` source code](https://github.com/Shazwazza/Examine/blob/master/src/Examine.Test/Lucene/Suggest/SuggesterApiTests.cs) to use as examples/reference._
+
+
+## Registering Suggesters
+
+On the index to register the Suggesters, create a SuggesterDefinitionCollection and set it on IndexOptions.SuggesterDefinitions
+
+Example
+
+```cs
+ var suggesters = new SuggesterDefinitionCollection();
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.AnalyzingInfixSuggester, ExamineLuceneSuggesterNames.AnalyzingInfixSuggester, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.AnalyzingSuggester, ExamineLuceneSuggesterNames.AnalyzingSuggester, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker, ExamineLuceneSuggesterNames.DirectSpellChecker, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker_LevensteinDistance, ExamineLuceneSuggesterNames.DirectSpellChecker_LevensteinDistance, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker_JaroWinklerDistance, ExamineLuceneSuggesterNames.DirectSpellChecker_JaroWinklerDistance, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.DirectSpellChecker_NGramDistance, ExamineLuceneSuggesterNames.DirectSpellChecker_NGramDistance, new string[] { "fullName" }));
+ suggesters.AddOrUpdate(new SuggesterDefinition(ExamineLuceneSuggesterNames.FuzzySuggester, ExamineLuceneSuggesterNames.FuzzySuggester, new string[] { "fullName" }));
+```
+
+## Suggester API
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new SuggestionOptions(5,ExamineLuceneSuggesterNames.AnalyzingSuggester));
+```
+
+This code will run a suggestion for the input text "Sam", returning up to 5 suggestions.
+
+## Lucene Suggesters
+
+To generate suggestions for input text, retreive the ISuggester from the index IIndex.Suggester.
+
+### Analyzing Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.AnalyzingInfixSuggester));
+```
+
+This code will run a suggestion for the input text "Sam", returning up to 5 suggestions, and will highlight the result text which matches the input text..
+
+### Analyzing Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.AnalyzingSuggester));
+```
+
+This code will run a suggestion for the input text "Sam", returning up to 5 suggestions.
+
+### Fuzzy Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.FuzzySuggester));
+```
+
+This code will run a Fuzzy suggestion for the input text "Sam", returning up to 5 suggestions.
+
+### Direct SpellChecker Suggester
+
+```cs
+var suggester = index.Suggester;
+var query = suggester.CreateSuggestionQuery();
+var results = query.Execute("Sam", new LuceneSuggestionOptions(5, ExamineLuceneSuggesterNames.DirectSpellChecker));
+```
+
+This code will run a spellchecker suggestion for the input text "Sam" returning up to 5 suggestions.
diff --git a/docs/templates/examinemodern/public/main.css b/docs/templates/examinemodern/public/main.css
new file mode 100644
index 000000000..98636c8b6
--- /dev/null
+++ b/docs/templates/examinemodern/public/main.css
@@ -0,0 +1,41 @@
+/* COLOR VARIABLES*/
+:root {
+ --header-bg-color: #159957;
+ --header-ft-color: #fff;
+ --highlight-light: #5e92f3;
+ --highlight-dark: #003c8f;
+ --accent-dim: #e0e0e0;
+ --accent-super-dim: #f3f3f3;
+ --font-color: #34393e;
+ --card-box-shadow: 0 1px 2px 0 rgba(61, 65, 68, 0.06), 0 1px 3px 1px rgba(61, 65, 68, 0.16);
+ --search-box-shadow: 0 1px 2px 0 rgba(41, 45, 48, 0.36), 0 1px 3px 1px rgba(41, 45, 48, 0.46);
+ --transition: 350ms;
+}
+/* Examine Docs Overrides */
+
+/* Logo */
+#logo {
+ vertical-align: middle;
+ width: 40px;
+ height: 40px;
+ background-color: #fff;
+ border-radius: 20px;
+ margin:5px;
+}
+/*
+.navbar {
+ color: var(--header-ft-color);
+ --bs-navbar-active-color: #fff;
+ --bs-nav-link-color: #fff;
+ background-color: var(--hergb(2, 2, 2)-bg-color);
+ background-image: linear-gradient(120deg, #155799, var(--header-bg-color));
+}
+
+.navbar-inverse .navbar-nav > li > a,
+.navbar-inverse .navbar-text {
+ background-color: transparent;
+}
+
+h1,h2,h3,h4,h5{
+ color: var(--highlight-dark);
+} */
\ No newline at end of file
diff --git a/docs/templates/material/partials/head.tmpl.partial b/docs/templates/material/partials/head.tmpl.partial
deleted file mode 100644
index 6ff01af7f..000000000
--- a/docs/templates/material/partials/head.tmpl.partial
+++ /dev/null
@@ -1,29 +0,0 @@
-{{!Copyright (c) Oscar Vasquez. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
-
-
-
-
- {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}
-
-
-
- {{#_description}}{{/_description}}
-
-
-
-
-
-
-
- {{#_noindex}}{{/_noindex}}
- {{#_enableSearch}}{{/_enableSearch}}
- {{#_enableNewTab}}{{/_enableNewTab}}
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/templates/material/styles/main.css b/docs/templates/material/styles/main.css
deleted file mode 100644
index 77d29effb..000000000
--- a/docs/templates/material/styles/main.css
+++ /dev/null
@@ -1,337 +0,0 @@
-/* COLOR VARIABLES*/
-:root {
- --header-bg-color: #159957;
- --header-ft-color: #fff;
- --highlight-light: #5e92f3;
- --highlight-dark: #003c8f;
- --accent-dim: #e0e0e0;
- --accent-super-dim: #f3f3f3;
- --font-color: #34393e;
- --card-box-shadow: 0 1px 2px 0 rgba(61, 65, 68, 0.06), 0 1px 3px 1px rgba(61, 65, 68, 0.16);
- --search-box-shadow: 0 1px 2px 0 rgba(41, 45, 48, 0.36), 0 1px 3px 1px rgba(41, 45, 48, 0.46);
- --transition: 350ms;
-}
-
-body {
- color: var(--font-color);
- font-family: "Roboto", sans-serif;
- line-height: 1.5;
- font-size: 16px;
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
- word-wrap: break-word;
-}
-
-/* HIGHLIGHT COLOR */
-
-button,
-a {
- color: var(--highlight-dark);
- cursor: pointer;
-}
-
-button:hover,
-button:focus,
-a:hover,
-a:focus {
- color: var(--highlight-light);
- text-decoration: none;
-}
-
-.toc .nav > li.active > a {
- color: var(--highlight-dark);
-}
-
-.toc .nav > li.active > a:hover,
-.toc .nav > li.active > a:focus {
- color: var(--highlight-light);
-}
-
-.pagination > .active > a {
- background-color: var(--header-bg-color);
- border-color: var(--header-bg-color);
-}
-
-.pagination > .active > a,
-.pagination > .active > a:focus,
-.pagination > .active > a:hover,
-.pagination > .active > span,
-.pagination > .active > span:focus,
-.pagination > .active > span:hover {
- background-color: var(--highlight-light);
- border-color: var(--highlight-light);
-}
-
-/* HEADINGS */
-
-h1 {
- font-weight: 600;
- font-size: 32px;
-}
-
-h2 {
- font-weight: 600;
- font-size: 24px;
- line-height: 1.8;
-}
-
-h3 {
- font-weight: 600;
- font-size: 20px;
- line-height: 1.8;
-}
-
-h5 {
- font-size: 14px;
- padding: 10px 0px;
-}
-
-article h1,
-article h2,
-article h3,
-article h4 {
- margin-top: 35px;
- margin-bottom: 15px;
-}
-
-article h4 {
- padding-bottom: 8px;
- border-bottom: 2px solid #ddd;
-}
-
-/* NAVBAR */
-
-.navbar-brand > img {
- color: var(--header-ft-color);
-}
-
-.navbar {
- border: none;
- /* Both navbars use box-shadow */
- -webkit-box-shadow: var(--card-box-shadow);
- -moz-box-shadow: var(--card-box-shadow);
- box-shadow: var(--card-box-shadow);
-}
-
-.subnav {
- border-top: 1px solid #ddd;
- background-color: #fff;
-}
-
-.navbar-inverse {
- background-color: var(--header-bg-color);
- z-index: 100;
-}
-
-.navbar-inverse .navbar-nav > li > a,
-.navbar-inverse .navbar-text {
- color: var(--header-ft-color);
- background-color: var(--header-bg-color);
- border-bottom: 3px solid transparent;
- padding-bottom: 12px;
- transition: 350ms;
-}
-
-.navbar-inverse .navbar-nav > li > a:focus,
-.navbar-inverse .navbar-nav > li > a:hover {
- color: var(--header-ft-color);
- background-color: var(--header-bg-color);
- border-bottom: 3px solid white;
-}
-
-.navbar-inverse .navbar-nav > .active > a,
-.navbar-inverse .navbar-nav > .active > a:focus,
-.navbar-inverse .navbar-nav > .active > a:hover {
- color: var(--header-ft-color);
- background-color: var(--header-bg-color);
- border-bottom: 3px solid white;
-}
-
-.navbar-form .form-control {
- border: 0;
- border-radius: 4px;
- box-shadow: var(--search-box-shadow);
- transition:var(--transition);
-}
-
-.navbar-form .form-control:hover {
- background-color: var(--accent-dim);
-}
-
-/* NAVBAR TOGGLED (small screens) */
-
-.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form {
- border: none;
-}
-.navbar-inverse .navbar-toggle {
- box-shadow: var(--card-box-shadow);
- border: none;
-}
-
-.navbar-inverse .navbar-toggle:focus,
-.navbar-inverse .navbar-toggle:hover {
- background-color: var(--highlight-dark);
-}
-
-/* SIDEBAR */
-
-.toc .level1 > li {
- font-weight: 400;
-}
-
-.toc .nav > li > a {
- color: var(--font-color);
-}
-
-.sidefilter {
- background-color: #fff;
- border-left: none;
- border-right: none;
-}
-
-.sidefilter {
- background-color: #fff;
- border-left: none;
- border-right: none;
-}
-
-.toc-filter {
- padding: 5px;
- margin: 0;
- box-shadow: var(--card-box-shadow);
- transition:var(--transition);
-}
-
-.toc-filter:hover {
- background-color: var(--accent-super-dim);
-}
-
-.toc-filter > input {
- border: none;
- background-color: inherit;
- transition: inherit;
-}
-
-.toc-filter > .filter-icon {
- display: none;
-}
-
-.sidetoc > .toc {
- background-color: #fff;
- overflow-x: hidden;
-}
-
-.sidetoc {
- background-color: #fff;
- border: none;
-}
-
-/* ALERTS */
-
-.alert {
- padding: 0px 0px 5px 0px;
- color: inherit;
- background-color: inherit;
- border: none;
- box-shadow: var(--card-box-shadow);
-}
-
-.alert > p {
- margin-bottom: 0;
- padding: 5px 10px;
-}
-
-.alert > ul {
- margin-bottom: 0;
- padding: 5px 40px;
-}
-
-.alert > h5 {
- padding: 10px 15px;
- margin-top: 0;
- text-transform: uppercase;
- font-weight: bold;
- border-radius: 4px 4px 0 0;
-}
-
-.alert-info > h5 {
- color: #1976d2;
- border-bottom: 4px solid #1976d2;
- background-color: #e3f2fd;
-}
-
-.alert-warning > h5 {
- color: #f57f17;
- border-bottom: 4px solid #f57f17;
- background-color: #fff3e0;
-}
-
-.alert-danger > h5 {
- color: #d32f2f;
- border-bottom: 4px solid #d32f2f;
- background-color: #ffebee;
-}
-
-/* CODE HIGHLIGHT */
-pre {
- padding: 9.5px;
- margin: 0 0 10px;
- font-size: 13px;
- word-break: break-all;
- word-wrap: break-word;
- background-color: #fffaef;
- border-radius: 4px;
- border: none;
- box-shadow: var(--card-box-shadow);
-}
-
-/* STYLE FOR IMAGES */
-
-.article .small-image {
- margin-top: 15px;
- box-shadow: var(--card-box-shadow);
- max-width: 350px;
-}
-
-.article .medium-image {
- margin-top: 15px;
- box-shadow: var(--card-box-shadow);
- max-width: 550px;
-}
-
-.article .large-image {
- margin-top: 15px;
- box-shadow: var(--card-box-shadow);
- max-width: 700px;
-}
-
-/* Examine Docs Overrides */
-
-/* Logo */
-#logo {
- vertical-align: middle;
- width: 40px;
- height: 40px;
- background-color: #fff;
- border-radius: 20px;
- margin:5px;
-}
-
-.navbar {
- color: var(--header-ft-color);
- background-color: var(--header-bg-color);
- background-image: linear-gradient(120deg, #155799, var(--header-bg-color));
-}
-
-.navbar-inverse .navbar-nav > li > a,
-.navbar-inverse .navbar-text {
- background-color: transparent;
-}
-
-.subnav.navbar * {
- color: var(--header-ft-color);
-}
-
-h1,h2,h3,h4,h5{
- color: var(--highlight-dark);
-}
\ No newline at end of file
diff --git a/docs/toc.yml b/docs/toc.yml
index f060c3a02..26c2e3d9b 100644
--- a/docs/toc.yml
+++ b/docs/toc.yml
@@ -1,9 +1,9 @@
- name: User Guide
- href: articles/
+ href: articles/toc.yml
- name: Api Documentation
href: api/
homepage: api/index.md
- name: Developer Guide
- href: developerguides/
+ href: developerguides/toc.yml
- name: Source Code
href: https://github.com/Shazwazza/Examine
diff --git a/src/Examine.Core/BaseIndexProvider.cs b/src/Examine.Core/BaseIndexProvider.cs
index f952396c4..2140aefea 100644
--- a/src/Examine.Core/BaseIndexProvider.cs
+++ b/src/Examine.Core/BaseIndexProvider.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Examine.Suggest;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -82,6 +83,10 @@ protected abstract void PerformDeleteFromIndex(IEnumerable itemIds,
///
public abstract ISearcher Searcher { get; }
+ ///
+ public abstract ISuggester Suggester { get; }
+
+ ///
///
/// Validates the items and calls
///
diff --git a/src/Examine.Core/ExamineManager.cs b/src/Examine.Core/ExamineManager.cs
index a057ea101..de185be21 100644
--- a/src/Examine.Core/ExamineManager.cs
+++ b/src/Examine.Core/ExamineManager.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using Examine.Suggest;
namespace Examine
{
@@ -14,7 +15,26 @@ public class ExamineManager : IDisposable, IExamineManager
///
public ExamineManager(IEnumerable indexes, IEnumerable searchers)
{
- foreach(var i in indexes)
+ foreach (var i in indexes)
+ {
+ AddIndex(i);
+ }
+
+ foreach (var s in searchers)
+ {
+ AddSearcher(s);
+ }
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Examine Indexes
+ /// Examine Searchers
+ /// Examine Suggesters
+ public ExamineManager(IEnumerable indexes, IEnumerable searchers, IEnumerable suggesters)
+ {
+ foreach(IIndex i in indexes)
{
AddIndex(i);
}
@@ -23,10 +43,16 @@ public ExamineManager(IEnumerable indexes, IEnumerable search
{
AddSearcher(s);
}
+
+ foreach (ISuggester s in suggesters)
+ {
+ AddSuggester(s);
+ }
}
private readonly ConcurrentDictionary _indexers = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase);
private readonly ConcurrentDictionary _searchers = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase);
+ private readonly ConcurrentDictionary _suggesters = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase);
///
public bool TryGetSearcher(string searcherName,
@@ -44,12 +70,20 @@ public bool TryGetIndex(string indexName,
out IIndex index) =>
(index = _indexers.TryGetValue(indexName, out var i) ? i : null) != null;
+
+ ///
+ public bool TryGetSuggester(string suggesterName, out ISuggester suggester) =>
+ (suggester = _suggesters.TryGetValue(suggesterName, out var s) ? s : null) != null;
+
///
public IEnumerable RegisteredSearchers => _searchers.Values;
///
public IEnumerable Indexes => _indexers.Values;
-
+
+ ///
+ public IEnumerable RegisteredSuggesters => _suggesters.Values;
+
private IIndex AddIndex(IIndex index)
{
//make sure this name doesn't exist in
@@ -72,6 +106,17 @@ private ISearcher AddSearcher(ISearcher searcher)
return searcher;
}
+ private ISuggester AddSuggester(ISuggester suggester)
+ {
+ //make sure this name doesn't exist in
+ if (!_suggesters.TryAdd(suggester.Name, suggester))
+ {
+ throw new InvalidOperationException("The suggester with name " + suggester.Name + " already exists");
+ }
+
+ return suggester;
+ }
+
///
/// Call this in Application_End.
///
@@ -122,7 +167,18 @@ public virtual void Stop(bool immediate)
{
// we don't want to kill the app or anything, even though it is terminating, best to just ensure that
// no strange lucene background thread stuff causes issues here.
- }
+ }
+ try
+ {
+ foreach (var suggester in RegisteredSuggesters.OfType())
+ {
+ suggester.Dispose();
+ }
+ }
+ catch {
+ // we don't want to kill the app or anything, even though it is terminating, best to just ensure that
+ // no strange lucene background thread stuff causes issues here.
+ }
}
else
{
diff --git a/src/Examine.Core/IExamineManager.cs b/src/Examine.Core/IExamineManager.cs
index c2583f246..5663aa8b0 100644
--- a/src/Examine.Core/IExamineManager.cs
+++ b/src/Examine.Core/IExamineManager.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using Examine.Suggest;
namespace Examine
{
@@ -25,6 +26,14 @@ public interface IExamineManager
///
IEnumerable RegisteredSearchers { get; }
+ ///
+ /// Gets a list of all manually configured suggester providers
+ ///
+ ///
+ /// This returns only those suggesters explicitly registered with AddSuggester or config based suggesters
+ ///
+ IEnumerable RegisteredSuggesters { get; }
+
///
/// Disposes the
///
@@ -56,5 +65,15 @@ bool TryGetSearcher(string searcherName,
#endif
out ISearcher searcher);
+ ///
+ /// Returns a sugesster that was registered with AddSuggester or via config
+ ///
+ ///
+ ///
+ ///
+ /// true if the suggester was found by name
+ ///
+ bool TryGetSuggester(string suggesterName, out ISuggester suggester);
+
}
}
diff --git a/src/Examine.Core/IIndex.cs b/src/Examine.Core/IIndex.cs
index b584abead..bc7c9c278 100644
--- a/src/Examine.Core/IIndex.cs
+++ b/src/Examine.Core/IIndex.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using Examine.Suggest;
namespace Examine
{
@@ -61,5 +62,11 @@ public interface IIndex
/// Occurs for an Indexing Error
///
event EventHandler IndexingError;
+
+ ///
+ /// Returns a suggester for the index
+ ///
+ ///
+ ISuggester Suggester { get; }
}
}
diff --git a/src/Examine.Core/IndexOptions.cs b/src/Examine.Core/IndexOptions.cs
index fc1bf4693..ddc5b7d88 100644
--- a/src/Examine.Core/IndexOptions.cs
+++ b/src/Examine.Core/IndexOptions.cs
@@ -5,10 +5,12 @@ namespace Examine
///
public class IndexOptions
{
+
///
public IndexOptions()
{
FieldDefinitions = new FieldDefinitionCollection();
+ SuggesterDefinitions = new SuggesterDefinitionCollection();
}
///
@@ -20,5 +22,10 @@ public IndexOptions()
/// The validator for the
///
public IValueSetValidator? Validator { get; set; }
+
+ ///
+ /// The suggester definitions for the
+ ///
+ public SuggesterDefinitionCollection SuggesterDefinitions { get; set; }
}
}
diff --git a/src/Examine.Core/ReadOnlySuggesterDefinitionCollection.cs b/src/Examine.Core/ReadOnlySuggesterDefinitionCollection.cs
new file mode 100644
index 000000000..36a9aa6e2
--- /dev/null
+++ b/src/Examine.Core/ReadOnlySuggesterDefinitionCollection.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Examine
+{
+ ///
+ /// Manages the mappings between a suggester name and it's index type
+ ///
+ public class ReadOnlySuggesterDefinitionCollection : IEnumerable
+ {
+ ///
+ /// Constructor
+ ///
+ public ReadOnlySuggesterDefinitionCollection()
+ : this(Enumerable.Empty())
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Suggester Definitions
+ public ReadOnlySuggesterDefinitionCollection(params SuggesterDefinition[] definitions)
+ : this((IEnumerable)definitions)
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Suggester Definitions
+ public ReadOnlySuggesterDefinitionCollection(IEnumerable definitions)
+ {
+ if (definitions == null)
+ return;
+
+ foreach (var s in definitions.GroupBy(x => x.Name))
+ {
+ var suggester = s.FirstOrDefault();
+ if (suggester != default)
+ {
+ Definitions.TryAdd(s.Key, suggester);
+ }
+ }
+ }
+
+ ///
+ /// Tries to get a by suggester name
+ ///
+ ///
+ ///
+ ///
+ /// returns true if one was found otherwise false
+ ///
+ ///
+ /// Marked as virtual so developers can inherit this class and override this method in case
+ /// suggester definitions are dynamic.
+ ///
+ public virtual bool TryGetValue(string suggesterName, out SuggesterDefinition suggesterDefinition) => Definitions.TryGetValue(suggesterName, out suggesterDefinition);
+
+ ///
+ /// Count of Suggesters
+ ///
+ public int Count => Definitions.Count;
+
+ ///
+ /// Suggester Definitions
+ ///
+ protected ConcurrentDictionary Definitions { get; } = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase);
+
+ ///
+ public IEnumerator GetEnumerator() => Definitions.Values.GetEnumerator();
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+}
diff --git a/src/Examine.Core/Suggest/BaseSuggesterProvider.cs b/src/Examine.Core/Suggest/BaseSuggesterProvider.cs
new file mode 100644
index 000000000..e6a551736
--- /dev/null
+++ b/src/Examine.Core/Suggest/BaseSuggesterProvider.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Examine.Suggest
+{
+ ///
+ public abstract class BaseSuggesterProvider : ISuggester
+ {
+ ///
+ protected BaseSuggesterProvider(string name)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ throw new ArgumentException("Value cannot be null or whitespace.", nameof(name));
+ Name = name;
+ }
+ ///
+ public string Name { get; }
+
+ ///
+ public abstract ISuggestionQuery CreateSuggestionQuery();
+
+ ///
+ public abstract ISuggestionResults Suggest(string searchText, SuggestionOptions? options = null);
+ }
+}
diff --git a/src/Examine.Core/Suggest/ISuggester.cs b/src/Examine.Core/Suggest/ISuggester.cs
new file mode 100644
index 000000000..706689a0d
--- /dev/null
+++ b/src/Examine.Core/Suggest/ISuggester.cs
@@ -0,0 +1,28 @@
+namespace Examine.Suggest
+{
+ ///
+ /// An interface representing an Examine Suggester.
+ ///
+ public interface ISuggester
+ {
+ ///
+ /// Suggester Name.
+ ///
+ string Name { get; }
+
+ ///
+ /// Suggest query terms for the given search Text
+ ///
+ /// Text to suggest on
+ /// Options
+ ///
+ ISuggestionResults Suggest(string searchText, SuggestionOptions? options = null);
+
+ ///
+ /// Creates a Suggestion Query
+ ///
+ /// Query
+ ISuggestionQuery CreateSuggestionQuery();
+
+ }
+}
diff --git a/src/Examine.Core/Suggest/ISuggestionExecutor.cs b/src/Examine.Core/Suggest/ISuggestionExecutor.cs
new file mode 100644
index 000000000..510d3b584
--- /dev/null
+++ b/src/Examine.Core/Suggest/ISuggestionExecutor.cs
@@ -0,0 +1,13 @@
+namespace Examine.Suggest
+{
+ ///
+ /// Executes a Suggester
+ ///
+ public interface ISuggestionExecutor
+ {
+ ///
+ /// Executes the query
+ ///
+ ISuggestionResults Execute(string searchText, SuggestionOptions? options = null);
+ }
+}
diff --git a/src/Examine.Core/Suggest/ISuggestionQuery.cs b/src/Examine.Core/Suggest/ISuggestionQuery.cs
new file mode 100644
index 000000000..71038db78
--- /dev/null
+++ b/src/Examine.Core/Suggest/ISuggestionQuery.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace Examine.Suggest
+{
+ ///
+ /// Search Suggestion Query
+ ///
+ public interface ISuggestionQuery : ISuggestionExecutor
+ {
+ }
+}
diff --git a/src/Examine.Core/Suggest/ISuggestionResult.cs b/src/Examine.Core/Suggest/ISuggestionResult.cs
new file mode 100644
index 000000000..14af7baac
--- /dev/null
+++ b/src/Examine.Core/Suggest/ISuggestionResult.cs
@@ -0,0 +1,23 @@
+namespace Examine.Suggest
+{
+ ///
+ /// Suggestion Result
+ ///
+ public interface ISuggestionResult
+ {
+ ///
+ /// Suggestion Text
+ ///
+ string Text { get; }
+
+ ///
+ /// Suggestion Weight
+ ///
+ float? Weight { get; }
+
+ ///
+ /// Frequency of Suggestion text occurance
+ ///
+ int? Frequency { get; }
+ }
+}
diff --git a/src/Examine.Core/Suggest/ISuggestionResults.cs b/src/Examine.Core/Suggest/ISuggestionResults.cs
new file mode 100644
index 000000000..395f043cf
--- /dev/null
+++ b/src/Examine.Core/Suggest/ISuggestionResults.cs
@@ -0,0 +1,12 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Examine.Suggest
+{
+ ///
+ /// Suggestion Results
+ ///
+ public interface ISuggestionResults : IEnumerable
+ {
+ }
+}
diff --git a/src/Examine.Core/Suggest/SuggestionOptions.cs b/src/Examine.Core/Suggest/SuggestionOptions.cs
new file mode 100644
index 000000000..e83976902
--- /dev/null
+++ b/src/Examine.Core/Suggest/SuggestionOptions.cs
@@ -0,0 +1,33 @@
+namespace Examine.Suggest
+{
+ ///
+ /// Suggester Options
+ ///
+ public class SuggestionOptions
+ {
+ ///
+ /// Constructor
+ ///
+ /// Clamp number of results
+ /// The name of the Suggester to use
+ public SuggestionOptions(int top = 5, string suggesterName = null)
+ {
+ Top = top;
+ if (top < 0)
+ {
+ top = 0;
+ }
+ SuggesterName = suggesterName;
+ }
+
+ ///
+ /// Clamp number of results.
+ ///
+ public int Top { get; }
+
+ ///
+ /// The name of the Suggester to use
+ ///
+ public string SuggesterName { get; }
+ }
+}
diff --git a/src/Examine.Core/Suggest/SuggestionResult.cs b/src/Examine.Core/Suggest/SuggestionResult.cs
new file mode 100644
index 000000000..edfb61834
--- /dev/null
+++ b/src/Examine.Core/Suggest/SuggestionResult.cs
@@ -0,0 +1,30 @@
+namespace Examine.Suggest
+{
+ ///
+ /// Suggestion Result
+ ///
+ public class SuggestionResult : ISuggestionResult
+ {
+ ///
+ /// Constructor
+ ///
+ /// Suggestion Text
+ /// Suggestion Weight
+ /// Suggestion Text frequency
+ public SuggestionResult(string text, float? weight = null, int? frequency = null)
+ {
+ Text = text;
+ Weight = weight;
+ Frequency = frequency;
+ }
+
+ ///
+ public string Text { get; }
+
+ ///
+ public float? Weight { get; }
+
+ ///
+ public int? Frequency { get; }
+ }
+}
diff --git a/src/Examine.Core/SuggesterDefinition.cs b/src/Examine.Core/SuggesterDefinition.cs
new file mode 100644
index 000000000..38c69f407
--- /dev/null
+++ b/src/Examine.Core/SuggesterDefinition.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Examine
+{
+ ///
+ /// Defines a suggester for an Index
+ ///
+ public class SuggesterDefinition
+ {
+ ///
+ /// Constructor
+ ///
+ /// Name of the suggester
+ /// Source Index Fields for the Suggester
+ public SuggesterDefinition(string name, string[]? sourceFields = null)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ throw new ArgumentException("Value cannot be null or whitespace.", nameof(name));
+ }
+
+ Name = name;
+ SourceFields = sourceFields;
+ }
+
+ ///
+ /// The name of the Suggester
+ ///
+ public string Name { get; }
+
+ ///
+ /// Suggester Source Fields
+ ///
+ public string[]? SourceFields { get; }
+
+ }
+}
diff --git a/src/Examine.Core/SuggesterDefinitionCollection.cs b/src/Examine.Core/SuggesterDefinitionCollection.cs
new file mode 100644
index 000000000..db255ed1c
--- /dev/null
+++ b/src/Examine.Core/SuggesterDefinitionCollection.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace Examine
+{
+ ///
+ /// Collection of Suggester Definitions on an Index
+ ///
+ public class SuggesterDefinitionCollection : ReadOnlySuggesterDefinitionCollection
+ {
+ ///
+ /// Constructor
+ ///
+ /// Suggester Definitions
+ public SuggesterDefinitionCollection(params SuggesterDefinition[] definitions) : base(definitions)
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ public SuggesterDefinitionCollection()
+ {
+ }
+
+ ///
+ /// Get or Add a Suggester Definition
+ ///
+ /// Name of Suggester
+ /// Function to add Suggester
+ ///
+ public SuggesterDefinition GetOrAdd(string suggesterName, Func add) => Definitions.GetOrAdd(suggesterName, add);
+
+ ///
+ /// Replace any definition with the specified one, if one doesn't exist then it is added
+ ///
+ ///
+ public void AddOrUpdate(SuggesterDefinition definition) => Definitions.AddOrUpdate(definition.Name, definition, (s, factory) => definition);
+
+ ///
+ /// Try Add a Suggester Definition
+ ///
+ /// Suggester Defintion
+ /// Whether the Suggester was added
+ public bool TryAdd(SuggesterDefinition definition) => Definitions.TryAdd(definition.Name, definition);
+ }
+}
diff --git a/src/Examine.Host/ServicesCollectionExtensions.cs b/src/Examine.Host/ServicesCollectionExtensions.cs
index 4d7c72614..bc87c198e 100644
--- a/src/Examine.Host/ServicesCollectionExtensions.cs
+++ b/src/Examine.Host/ServicesCollectionExtensions.cs
@@ -5,6 +5,8 @@
using Examine.Lucene;
using Examine.Lucene.Directories;
using Examine.Lucene.Providers;
+using Examine.Lucene.Suggest;
+using Examine.Suggest;
using Lucene.Net.Analysis;
using Lucene.Net.Facet;
using Microsoft.Extensions.DependencyInjection;
@@ -148,7 +150,7 @@ public static IServiceCollection AddExamineLuceneIndex(
///
///
///
- /// A factory to fullfill the custom searcher construction parameters excluding the name that are not already registerd in DI.
+ /// A factory to fullfill the custom searcher construction parameters excluding the name that are not already registered in DI.
///
///
public static IServiceCollection AddExamineSearcher(
@@ -261,5 +263,32 @@ public static IServiceCollection AddExamine(this IServiceCollection services, Di
return services;
}
+
+ ///
+ /// Registers a standalone Examine suggester
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A factory to fullfill the custom suggester construction parameters excluding the name that are not already registerd in DI.
+ ///
+ ///
+ public static IServiceCollection AddExamineSuggester(
+ this IServiceCollection serviceCollection,
+ string name,
+ Func> parameterFactory)
+ where TSuggester : ISuggester
+ => serviceCollection.AddTransient(services =>
+ {
+ IList