You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2017/07/06 13:07:08 UTC
[11/14] lucenenet git commit: Ported Lucene.Net.Demo + tests (minus
the FormBasedXmlQueryDemo QueryParser.Xml demo)
Ported Lucene.Net.Demo + tests (minus the FormBasedXmlQueryDemo QueryParser.Xml demo)
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/775df654
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/775df654
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/775df654
Branch: refs/heads/master
Commit: 775df65469e68271dc0610f91f13c4819034aa4b
Parents: bfccac0
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Jul 6 18:41:46 2017 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Thu Jul 6 18:41:46 2017 +0700
----------------------------------------------------------------------
Lucene.Net.Portable.sln | 20 +
Lucene.Net.sln | 52 ++
.../Facet/AssociationsFacetsExample.cs | 178 +++++
.../Facet/DistanceFacetsExample.cs | 275 ++++++++
.../Facet/ExpressionAggregationFacetsExample.cs | 129 ++++
.../Facet/MultiCategoryListsFacetsExample.cs | 148 ++++
src/Lucene.Net.Demo/Facet/RangeFacetsExample.cs | 151 +++++
.../Facet/SimpleFacetsExample.cs | 274 ++++++++
.../Facet/SimpleSortedSetFacetsExample.cs | 171 +++++
src/Lucene.Net.Demo/IndexFiles.cs | 223 ++++++
src/Lucene.Net.Demo/Lucene.Net.Demo.csproj | 119 ++++
.../Lucene.Net.Demo.project.json | 8 +
src/Lucene.Net.Demo/Lucene.Net.Demo.xproj | 21 +
src/Lucene.Net.Demo/Properties/AssemblyInfo.cs | 51 ++
src/Lucene.Net.Demo/SearchFiles.cs | 313 +++++++++
src/Lucene.Net.Demo/project.json | 45 ++
src/Lucene.Net.Facet/DrillSideways.cs | 2 +-
src/Lucene.Net.Facet/FacetResult.cs | 1 +
.../Facet/TestAssociationsFacetsExample.cs | 44 ++
.../Facet/TestDistanceFacetsExample.cs | 50 ++
.../TestExpressionAggregationFacetsExample.cs | 36 +
.../TestMultiCategoryListsFacetsExample.cs | 37 +
.../Facet/TestRangeFacetsExample.cs | 50 ++
.../Facet/TestSimpleFacetsExample.cs | 61 ++
.../Facet/TestSimpleSortedSetFacetsExample.cs | 45 ++
.../Lucene.Net.Tests.Demo.csproj | 125 ++++
.../Lucene.Net.Tests.Demo.project.json | 11 +
.../Lucene.Net.Tests.Demo.xproj | 22 +
.../Properties/AssemblyInfo.cs | 42 ++
.../Test-Files/Docs/apache1.0.txt | 56 ++
.../Test-Files/Docs/apache1.1.txt | 58 ++
.../Test-Files/Docs/apache2.0.txt | 201 ++++++
.../Test-Files/Docs/cpl1.0.txt | 74 ++
.../Test-Files/Docs/epl1.0.txt | 88 +++
.../Test-Files/Docs/freebsd.txt | 10 +
.../Test-Files/Docs/gpl1.0.txt | 250 +++++++
.../Test-Files/Docs/gpl2.0.txt | 339 ++++++++++
.../Test-Files/Docs/gpl3.0.txt | 674 +++++++++++++++++++
.../Test-Files/Docs/lgpl2.1.txt | 504 ++++++++++++++
.../Test-Files/Docs/lgpl3.txt | 165 +++++
.../Test-Files/Docs/lpgl2.0.txt | 481 +++++++++++++
.../Test-Files/Docs/mit.txt | 22 +
.../Test-Files/Docs/mozilla1.1.txt | 470 +++++++++++++
.../Test-Files/Docs/mozilla_eula_firefox3.txt | 29 +
.../Docs/mozilla_eula_thunderbird2.txt | 27 +
src/Lucene.Net.Tests.Demo/TestDemo.cs | 101 +++
src/Lucene.Net.Tests.Demo/project.json | 47 ++
47 files changed, 6299 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/Lucene.Net.Portable.sln
----------------------------------------------------------------------
diff --git a/Lucene.Net.Portable.sln b/Lucene.Net.Portable.sln
index 0b7f53e..9e3b91d 100644
--- a/Lucene.Net.Portable.sln
+++ b/Lucene.Net.Portable.sln
@@ -93,6 +93,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Lucene.Net.Analysis.Phoneti
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Lucene.Net.Tests.Analysis.Phonetic", "src\Lucene.Net.Tests.Analysis.Phonetic\Lucene.Net.Tests.Analysis.Phonetic.xproj", "{1FE12EF7-4C89-4D49-BDD1-E49DC285F21B}"
EndProject
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Lucene.Net.Demo", "src\Lucene.Net.Demo\Lucene.Net.Demo.xproj", "{4BCD7980-0CF4-4DA0-B069-F555A41CB44D}"
+EndProject
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Lucene.Net.Tests.Demo", "src\Lucene.Net.Tests.Demo\Lucene.Net.Tests.Demo.xproj", "{93DF8BAA-9CAA-4142-8E96-55481188C012}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -429,6 +433,22 @@ Global
{1FE12EF7-4C89-4D49-BDD1-E49DC285F21B}.Release|Any CPU.Build.0 = Release|Any CPU
{1FE12EF7-4C89-4D49-BDD1-E49DC285F21B}.Release|x86.ActiveCfg = Release|Any CPU
{1FE12EF7-4C89-4D49-BDD1-E49DC285F21B}.Release|x86.Build.0 = Release|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Debug|x86.Build.0 = Debug|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Release|x86.ActiveCfg = Release|Any CPU
+ {4BCD7980-0CF4-4DA0-B069-F555A41CB44D}.Release|x86.Build.0 = Release|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Debug|x86.Build.0 = Debug|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Release|Any CPU.Build.0 = Release|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Release|x86.ActiveCfg = Release|Any CPU
+ {93DF8BAA-9CAA-4142-8E96-55481188C012}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/Lucene.Net.sln
----------------------------------------------------------------------
diff --git a/Lucene.Net.sln b/Lucene.Net.sln
index 74a64a3..a187ccc 100644
--- a/Lucene.Net.sln
+++ b/Lucene.Net.sln
@@ -102,6 +102,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Analysis.Phoneti
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Analysis.Phonetic", "src\Lucene.Net.Tests.Analysis.Phonetic\Lucene.Net.Tests.Analysis.Phonetic.csproj", "{A2867797-0A5D-4878-8F59-58C399C9A4E4}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Demo", "src\Lucene.Net.Demo\Lucene.Net.Demo.csproj", "{D1661154-8F5B-499A-8B2D-04B8A67F4232}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Demo", "src\Lucene.Net.Tests.Demo\Lucene.Net.Tests.Demo.csproj", "{571B361E-B0D4-445E-A0BC-1A24AA184258}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1007,6 +1011,54 @@ Global
{A2867797-0A5D-4878-8F59-58C399C9A4E4}.Release35|Mixed Platforms.Build.0 = Release|Any CPU
{A2867797-0A5D-4878-8F59-58C399C9A4E4}.Release35|x86.ActiveCfg = Release|Any CPU
{A2867797-0A5D-4878-8F59-58C399C9A4E4}.Release35|x86.Build.0 = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug35|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug35|Any CPU.Build.0 = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug35|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug35|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug35|x86.ActiveCfg = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Debug35|x86.Build.0 = Debug|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release|x86.Build.0 = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release35|Any CPU.ActiveCfg = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release35|Any CPU.Build.0 = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release35|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release35|Mixed Platforms.Build.0 = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release35|x86.ActiveCfg = Release|Any CPU
+ {D1661154-8F5B-499A-8B2D-04B8A67F4232}.Release35|x86.Build.0 = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug|x86.Build.0 = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug35|Any CPU.ActiveCfg = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug35|Any CPU.Build.0 = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug35|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug35|Mixed Platforms.Build.0 = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug35|x86.ActiveCfg = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Debug35|x86.Build.0 = Debug|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release|Any CPU.Build.0 = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release|x86.ActiveCfg = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release|x86.Build.0 = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release35|Any CPU.ActiveCfg = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release35|Any CPU.Build.0 = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release35|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release35|Mixed Platforms.Build.0 = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release35|x86.ActiveCfg = Release|Any CPU
+ {571B361E-B0D4-445E-A0BC-1A24AA184258}.Release35|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/AssociationsFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/AssociationsFacetsExample.cs b/src/Lucene.Net.Demo/Facet/AssociationsFacetsExample.cs
new file mode 100644
index 0000000..f3649d0
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/AssociationsFacetsExample.cs
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.Taxonomy;
+using Lucene.Net.Facet.Taxonomy.Directory;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Shows example usage of category associations.
+ /// </summary>
+ public class AssociationsFacetsExample
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private readonly Directory taxoDir = new RAMDirectory();
+ private readonly FacetsConfig config;
+
+ /// <summary>Empty constructor</summary>
+ public AssociationsFacetsExample()
+ {
+ config = new FacetsConfig();
+ config.SetMultiValued("tags", true);
+ config.SetIndexFieldName("tags", "$tags");
+ config.SetMultiValued("genre", true);
+ config.SetIndexFieldName("genre", "$genre");
+ }
+
+ /// <summary>Build the example index.</summary>
+ private void Index()
+ {
+ IndexWriterConfig iwc = new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION));
+ using (IndexWriter indexWriter = new IndexWriter(indexDir, iwc))
+
+ // Writes facet ords to a separate directory from the main index
+ using (DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir))
+ {
+
+ Document doc = new Document();
+ // 3 occurrences for tag 'lucene'
+
+ // LUCENENET TODO: Create extension methods for built-in field types ( .AddFacetField("", ""), .AddInt32AssociationsFacetField(), etc ).
+ doc.Add(new Int32AssociationFacetField(3, "tags", "lucene"));
+ // 87% confidence level of genre 'computing'
+ doc.Add(new SingleAssociationFacetField(0.87f, "genre", "computing"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ // 1 occurrence for tag 'lucene'
+ doc.Add(new Int32AssociationFacetField(1, "tags", "lucene"));
+ // 2 occurrence for tag 'solr'
+ doc.Add(new Int32AssociationFacetField(2, "tags", "solr"));
+ // 75% confidence level of genre 'computing'
+ doc.Add(new SingleAssociationFacetField(0.75f, "genre", "computing"));
+ // 34% confidence level of genre 'software'
+ doc.Add(new SingleAssociationFacetField(0.34f, "genre", "software"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ } // Disposes indexWriter and taxoWriter
+ }
+
+ /// <summary>User runs a query and aggregates facets by summing their association values.</summary>
+ private IList<FacetResult> SumAssociations()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ FacetsCollector fc = new FacetsCollector();
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+
+ Facets tags = new TaxonomyFacetSumInt32Associations("$tags", taxoReader, config, fc);
+ Facets genre = new TaxonomyFacetSumSingleAssociations("$genre", taxoReader, config, fc);
+
+ // Retrieve results
+ IList<FacetResult> results = new List<FacetResult>();
+
+ results.Add(tags.GetTopChildren(10, "tags"));
+ results.Add(genre.GetTopChildren(10, "genre"));
+
+ return results;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>User drills down on 'tags/solr'.</summary>
+ private FacetResult DrillDown()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ // Passing no baseQuery means we drill down on all
+ // documents ("browse only"):
+ DrillDownQuery q = new DrillDownQuery(config);
+
+ // Now user drills down on Publish Date/2010:
+ q.Add("tags", "solr");
+ FacetsCollector fc = new FacetsCollector();
+ FacetsCollector.Search(searcher, q, 10, fc);
+
+ // Retrieve results
+ Facets facets = new TaxonomyFacetSumSingleAssociations("$genre", taxoReader, config, fc);
+ FacetResult result = facets.GetTopChildren(10, "genre");
+
+ return result;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>Runs summing association example.</summary>
+ public IList<FacetResult> RunSumAssociations()
+ {
+ Index();
+ return SumAssociations();
+ }
+
+ /// <summary>Runs the drill-down example.</summary>
+ public FacetResult RunDrillDown()
+ {
+ Index();
+ return DrillDown();
+ }
+
+ /// <summary>Runs the sum int/float associations examples and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Sum associations example:");
+ Console.WriteLine("-------------------------");
+ IList<FacetResult> results = new AssociationsFacetsExample().RunSumAssociations();
+ Console.WriteLine("tags: " + results[0]);
+ Console.WriteLine("genre: " + results[1]);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/DistanceFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/DistanceFacetsExample.cs b/src/Lucene.Net.Demo/Facet/DistanceFacetsExample.cs
new file mode 100644
index 0000000..5c5c7d8
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/DistanceFacetsExample.cs
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Expressions
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Expressions;
+using Lucene.Net.Expressions.JS;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.Range;
+using Lucene.Net.Facet.Taxonomy;
+using Lucene.Net.Index;
+using Lucene.Net.Queries;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using System;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Shows simple usage of dynamic range faceting, using the
+ /// expressions module to calculate distance.
+ /// </summary>
+ public class DistanceFacetsExample : IDisposable
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ internal static readonly DoubleRange ONE_KM = new DoubleRange("< 1 km", 0.0, true, 1.0, false);
+ internal static readonly DoubleRange TWO_KM = new DoubleRange("< 2 km", 0.0, true, 2.0, false);
+ internal static readonly DoubleRange FIVE_KM = new DoubleRange("< 5 km", 0.0, true, 5.0, false);
+ internal static readonly DoubleRange TEN_KM = new DoubleRange("< 10 km", 0.0, true, 10.0, false);
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private IndexSearcher searcher;
+ private readonly FacetsConfig config = new FacetsConfig();
+
+ /// <summary>The "home" latitude.</summary>
+ public readonly static double ORIGIN_LATITUDE = 40.7143528;
+
+ /// <summary>The "home" longitude.</summary>
+ public readonly static double ORIGIN_LONGITUDE = -74.0059731;
+
+ /// <summary>
+ /// Radius of the Earth in KM
+ /// <para/>
+ /// NOTE: this is approximate, because the earth is a bit
+ /// wider at the equator than the poles. See
+ /// http://en.wikipedia.org/wiki/Earth_radius
+ /// </summary>
+ public readonly static double EARTH_RADIUS_KM = 6371.01;
+
+ /// <summary>Build the example index.</summary>
+ public void Index()
+ {
+ using (IndexWriter writer = new IndexWriter(indexDir, new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION))))
+ {
+ // TODO: we could index in radians instead ... saves all the conversions in GetBoundingBoxFilter
+
+ // Add documents with latitude/longitude location:
+ Document doc = new Document();
+ doc.Add(new DoubleField("latitude", 40.759011, Field.Store.NO));
+ doc.Add(new DoubleField("longitude", -73.9844722, Field.Store.NO));
+ writer.AddDocument(doc);
+
+ doc = new Document();
+ doc.Add(new DoubleField("latitude", 40.718266, Field.Store.NO));
+ doc.Add(new DoubleField("longitude", -74.007819, Field.Store.NO));
+ writer.AddDocument(doc);
+
+ doc = new Document();
+ doc.Add(new DoubleField("latitude", 40.7051157, Field.Store.NO));
+ doc.Add(new DoubleField("longitude", -74.0088305, Field.Store.NO));
+ writer.AddDocument(doc);
+
+ // Open near-real-time searcher
+ searcher = new IndexSearcher(DirectoryReader.Open(writer, true));
+
+ } // Disposes writer
+ }
+
+ private ValueSource GetDistanceValueSource()
+ {
+ Expression distance = JavascriptCompiler.Compile(
+ string.Format(CultureInfo.InvariantCulture, "haversin({0:R},{1:R},latitude,longitude)", ORIGIN_LATITUDE, ORIGIN_LONGITUDE));
+
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.Add(new SortField("latitude", SortFieldType.DOUBLE));
+ bindings.Add(new SortField("longitude", SortFieldType.DOUBLE));
+
+ return distance.GetValueSource(bindings);
+ }
+
+ /// <summary>
+ /// Given a latitude and longitude (in degrees) and the
+ /// maximum great circle (surface of the earth) distance,
+ /// returns a simple Filter bounding box to "fast match"
+ /// candidates.
+ /// </summary>
+ public static Filter GetBoundingBoxFilter(double originLat, double originLng, double maxDistanceKM)
+ {
+ // Basic bounding box geo math from
+ // http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates,
+ // licensed under creative commons 3.0:
+ // http://creativecommons.org/licenses/by/3.0
+
+ // TODO: maybe switch to recursive prefix tree instead
+ // (in lucene/spatial)? It should be more efficient
+ // since it's a 2D trie...
+
+ // Degrees -> Radians:
+ double originLatRadians = originLat.ToRadians();
+ double originLngRadians = originLng.ToRadians();
+
+ double angle = maxDistanceKM / (SloppyMath.EarthDiameter(originLat) / 2.0);
+
+ double minLat = originLatRadians - angle;
+ double maxLat = originLatRadians + angle;
+
+ double minLng;
+ double maxLng;
+ if (minLat > -90.ToRadians() && maxLat < 90.ToRadians())
+ {
+ double delta = Math.Asin(Math.Sin(angle) / Math.Cos(originLatRadians));
+ minLng = originLngRadians - delta;
+ if (minLng < -180.ToRadians())
+ {
+ minLng += 2 * Math.PI;
+ }
+ maxLng = originLngRadians + delta;
+ if (maxLng > 180.ToRadians())
+ {
+ maxLng -= 2 * Math.PI;
+ }
+ }
+ else
+ {
+ // The query includes a pole!
+ minLat = Math.Max(minLat, -90.ToRadians());
+ maxLat = Math.Min(maxLat, 90.ToRadians());
+ minLng = -180.ToRadians();
+ maxLng = 180.ToRadians();
+ }
+
+ BooleanFilter f = new BooleanFilter();
+
+ // Add latitude range filter:
+ f.Add(NumericRangeFilter.NewDoubleRange("latitude", minLat.ToDegrees(), maxLat.ToDegrees(), true, true),
+ Occur.MUST);
+
+ // Add longitude range filter:
+ if (minLng > maxLng)
+ {
+ // The bounding box crosses the international date
+ // line:
+ BooleanFilter lonF = new BooleanFilter();
+ lonF.Add(NumericRangeFilter.NewDoubleRange("longitude", minLng.ToDegrees(), null, true, true),
+ Occur.SHOULD);
+ lonF.Add(NumericRangeFilter.NewDoubleRange("longitude", null, maxLng.ToDegrees(), true, true),
+ Occur.SHOULD);
+ f.Add(lonF, Occur.MUST);
+ }
+ else
+ {
+ f.Add(NumericRangeFilter.NewDoubleRange("longitude", minLng.ToDegrees(), maxLng.ToDegrees(), true, true),
+ Occur.MUST);
+ }
+
+ return f;
+ }
+
+ /// <summary>User runs a query and counts facets.</summary>
+ public FacetResult Search()
+ {
+ FacetsCollector fc = new FacetsCollector();
+
+ searcher.Search(new MatchAllDocsQuery(), fc);
+
+ Facets facets = new DoubleRangeFacetCounts("field", GetDistanceValueSource(), fc,
+ GetBoundingBoxFilter(ORIGIN_LATITUDE, ORIGIN_LONGITUDE, 10.0),
+ ONE_KM,
+ TWO_KM,
+ FIVE_KM,
+ TEN_KM);
+
+ return facets.GetTopChildren(10, "field");
+ }
+
+ /// <summary>User drills down on the specified range.</summary>
+ public TopDocs DrillDown(DoubleRange range)
+ {
+ // Passing no baseQuery means we drill down on all
+ // documents ("browse only"):
+ DrillDownQuery q = new DrillDownQuery(null);
+ ValueSource vs = GetDistanceValueSource();
+ q.Add("field", range.GetFilter(GetBoundingBoxFilter(ORIGIN_LATITUDE, ORIGIN_LONGITUDE, range.Max), vs));
+ DrillSideways ds = new SearchDrillSideways(searcher, config, vs);
+ return ds.Search(q, 10).Hits;
+ }
+
+ private class SearchDrillSideways : DrillSideways
+ {
+ private readonly ValueSource vs;
+
+ public SearchDrillSideways(IndexSearcher indexSearcher, FacetsConfig facetsConfig, ValueSource valueSource)
+ : base(indexSearcher, facetsConfig, (TaxonomyReader)null)
+ {
+ this.vs = valueSource;
+ }
+
+ protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
+ {
+ Debug.Assert(drillSideways.Length == 1);
+ return new DoubleRangeFacetCounts("field", vs, drillSideways[0], ONE_KM, TWO_KM, FIVE_KM, TEN_KM);
+ }
+ }
+
+ public void Dispose()
+ {
+ searcher?.IndexReader?.Dispose();
+ indexDir?.Dispose();
+ }
+
+ /// <summary>Runs the search and drill-down examples and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ using (DistanceFacetsExample example = new DistanceFacetsExample())
+ {
+ example.Index();
+
+ Console.WriteLine("Distance facet counting example:");
+ Console.WriteLine("-----------------------");
+ Console.WriteLine(example.Search());
+
+ Console.WriteLine("\n");
+ Console.WriteLine("Distance facet drill-down example (field/< 2 km):");
+ Console.WriteLine("---------------------------------------------");
+ TopDocs hits = example.DrillDown(TWO_KM);
+ Console.WriteLine(hits.TotalHits + " totalHits");
+
+ } // Disposes example
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/ExpressionAggregationFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/ExpressionAggregationFacetsExample.cs b/src/Lucene.Net.Demo/Facet/ExpressionAggregationFacetsExample.cs
new file mode 100644
index 0000000..c080b5a
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/ExpressionAggregationFacetsExample.cs
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Expressions
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Expressions;
+using Lucene.Net.Expressions.JS;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.Taxonomy;
+using Lucene.Net.Facet.Taxonomy.Directory;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Shows facets aggregation by an expression.
+ /// </summary>
+ public class ExpressionAggregationFacetsExample
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private readonly Directory taxoDir = new RAMDirectory();
+ private readonly FacetsConfig config = new FacetsConfig();
+
+ /// <summary>Build the example index.</summary>
+ private void Index()
+ {
+ using (IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION))))
+ // Writes facet ords to a separate directory from the main index
+ using (DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir))
+ {
+
+ Document doc = new Document();
+ doc.Add(new TextField("c", "foo bar", Field.Store.NO));
+ doc.Add(new NumericDocValuesField("popularity", 5L));
+ doc.Add(new FacetField("A", "B"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new TextField("c", "foo foo bar", Field.Store.NO));
+ doc.Add(new NumericDocValuesField("popularity", 3L));
+ doc.Add(new FacetField("A", "C"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ } // Disposes indexWriter and taxoWriter
+ }
+
+ /// <summary>User runs a query and aggregates facets.</summary>
+ private FacetResult Search()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ // Aggregate categories by an expression that combines the document's score
+ // and its popularity field
+ Expression expr = JavascriptCompiler.Compile("_score * sqrt(popularity)");
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.Add(new SortField("_score", SortFieldType.SCORE)); // the score of the document
+ bindings.Add(new SortField("popularity", SortFieldType.INT64)); // the value of the 'popularity' field
+
+ // Aggregates the facet values
+ FacetsCollector fc = new FacetsCollector(true);
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+
+ // Retrieve results
+ Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, expr.GetValueSource(bindings));
+ FacetResult result = facets.GetTopChildren(10, "A");
+
+ return result;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>Runs the search example.</summary>
+ public FacetResult RunSearch()
+ {
+ Index();
+ return Search();
+ }
+
+ /// <summary>Runs the search and drill-down examples and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Facet counting example:");
+ Console.WriteLine("-----------------------");
+ FacetResult result = new ExpressionAggregationFacetsExample().RunSearch();
+ Console.WriteLine(result);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/MultiCategoryListsFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/MultiCategoryListsFacetsExample.cs b/src/Lucene.Net.Demo/Facet/MultiCategoryListsFacetsExample.cs
new file mode 100644
index 0000000..a99fb4d
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/MultiCategoryListsFacetsExample.cs
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.Taxonomy;
+using Lucene.Net.Facet.Taxonomy.Directory;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Demonstrates indexing categories into different indexed fields.
+ /// </summary>
+ public class MultiCategoryListsFacetsExample
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private readonly Directory taxoDir = new RAMDirectory();
+ private readonly FacetsConfig config = new FacetsConfig();
+
+ /// <summary>Creates a new instance and populates the catetory list params mapping.</summary>
+ public MultiCategoryListsFacetsExample()
+ {
+ config.SetIndexFieldName("Author", "author");
+ config.SetIndexFieldName("Publish Date", "pubdate");
+ config.SetHierarchical("Publish Date", true);
+ }
+
+ /// <summary>Build the example index.</summary>
+ private void Index()
+ {
+ using (IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION))))
+ // Writes facet ords to a separate directory from the main index
+ using (DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir))
+ {
+ Document doc = new Document();
+
+ doc.Add(new FacetField("Author", "Bob"));
+ doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Lisa"));
+ doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Lisa"));
+ doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Susan"));
+ doc.Add(new FacetField("Publish Date", "2012", "1", "7"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Frank"));
+ doc.Add(new FacetField("Publish Date", "1999", "5", "5"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ } // Disposes indexWriter and taxoWriter
+ }
+
+ /// <summary>User runs a query and counts facets.</summary>
+ private IList<FacetResult> Search()
+ {
+ IList<FacetResult> results = new List<FacetResult>();
+
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+ FacetsCollector fc = new FacetsCollector();
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+
+ // Retrieve results
+
+ // Count both "Publish Date" and "Author" dimensions
+ Facets author = new FastTaxonomyFacetCounts("author", taxoReader, config, fc);
+ results.Add(author.GetTopChildren(10, "Author"));
+
+ Facets pubDate = new FastTaxonomyFacetCounts("pubdate", taxoReader, config, fc);
+ results.Add(pubDate.GetTopChildren(10, "Publish Date"));
+
+ } // Disposes indexReader and taxoReader
+
+ return results;
+ }
+
+ /// <summary>Runs the search example.</summary>
+ public IList<FacetResult> RunSearch()
+ {
+ Index();
+ return Search();
+ }
+
+ /// <summary>Runs the search example and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Facet counting over multiple category lists example:");
+ Console.WriteLine("-----------------------");
+ IList<FacetResult> results = new MultiCategoryListsFacetsExample().RunSearch();
+
+ Console.WriteLine("Author: " + results[0]);
+ Console.WriteLine("Publish Date: " + results[1]);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/RangeFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/RangeFacetsExample.cs b/src/Lucene.Net.Demo/Facet/RangeFacetsExample.cs
new file mode 100644
index 0000000..180c39b
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/RangeFacetsExample.cs
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.Range;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Shows simple usage of dynamic range faceting.
+ /// </summary>
+ public class RangeFacetsExample : IDisposable
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private IndexSearcher searcher;
+ private readonly long nowSec = DateTime.Now.Ticks;
+
+ internal readonly Int64Range PAST_HOUR;
+ internal readonly Int64Range PAST_SIX_HOURS;
+ internal readonly Int64Range PAST_DAY;
+
+ /// <summary>Constructor</summary>
+ public RangeFacetsExample()
+ {
+ PAST_HOUR = new Int64Range("Past hour", nowSec - 3600, true, nowSec, true);
+ PAST_SIX_HOURS = new Int64Range("Past six hours", nowSec - 6 * 3600, true, nowSec, true);
+ PAST_DAY = new Int64Range("Past day", nowSec - 24 * 3600, true, nowSec, true);
+ }
+
+ /// <summary>Build the example index.</summary>
+ public void Index()
+ {
+ using (IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION))))
+ {
+ // Add documents with a fake timestamp, 1000 sec before
+ // "now", 2000 sec before "now", ...:
+ for (int i = 0; i < 100; i++)
+ {
+ Document doc = new Document();
+ long then = nowSec - i * 1000;
+ // Add as doc values field, so we can compute range facets:
+ doc.Add(new NumericDocValuesField("timestamp", then));
+ // Add as numeric field so we can drill-down:
+ doc.Add(new Int64Field("timestamp", then, Field.Store.NO));
+ indexWriter.AddDocument(doc);
+ }
+
+ // Open near-real-time searcher
+ searcher = new IndexSearcher(DirectoryReader.Open(indexWriter, true));
+
+ } // Disposes indexWriter
+ }
+
+ private FacetsConfig GetConfig()
+ {
+ return new FacetsConfig();
+ }
+
+ /// <summary>User runs a query and counts facets.</summary>
+ public FacetResult Search()
+ {
+ // Aggregates the facet counts
+ FacetsCollector fc = new FacetsCollector();
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+
+ Facets facets = new Int64RangeFacetCounts("timestamp", fc,
+ PAST_HOUR,
+ PAST_SIX_HOURS,
+ PAST_DAY);
+ return facets.GetTopChildren(10, "timestamp");
+ }
+
+ /// <summary>User drills down on the specified range.</summary>
+ public TopDocs DrillDown(Int64Range range)
+ {
+ // Passing no baseQuery means we drill down on all
+ // documents ("browse only"):
+ DrillDownQuery q = new DrillDownQuery(GetConfig());
+
+ q.Add("timestamp", NumericRangeQuery.NewInt64Range("timestamp", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
+
+ return searcher.Search(q, 10);
+ }
+
+ public void Dispose()
+ {
+ searcher?.IndexReader?.Dispose();
+ indexDir?.Dispose();
+ }
+
+ /// <summary>Runs the search and drill-down examples and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ using (RangeFacetsExample example = new RangeFacetsExample())
+ {
+ example.Index();
+
+ Console.WriteLine("Facet counting example:");
+ Console.WriteLine("-----------------------");
+ Console.WriteLine(example.Search());
+
+ Console.WriteLine("\n");
+ Console.WriteLine("Facet drill-down example (timestamp/Past six hours):");
+ Console.WriteLine("---------------------------------------------");
+ TopDocs hits = example.DrillDown(example.PAST_SIX_HOURS);
+ Console.WriteLine(hits.TotalHits + " TotalHits");
+
+ } // Disposes example
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/SimpleFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/SimpleFacetsExample.cs b/src/Lucene.Net.Demo/Facet/SimpleFacetsExample.cs
new file mode 100644
index 0000000..1e5b49b
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/SimpleFacetsExample.cs
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.Taxonomy;
+using Lucene.Net.Facet.Taxonomy.Directory;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Shows simple usage of faceted indexing and search.
+ /// </summary>
+ public class SimpleFacetsExample
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private readonly Directory taxoDir = new RAMDirectory();
+ private readonly FacetsConfig config = new FacetsConfig();
+
+ /// <summary>Constructor</summary>
+ public SimpleFacetsExample()
+ {
+ config.SetHierarchical("Publish Date", true);
+ }
+
+ /// <summary>Build the example index.</summary>
+ private void Index()
+ {
+ using (IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION))))
+
+ // Writes facet ords to a separate directory from the main index
+ using (DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir))
+ {
+
+ Document doc = new Document();
+ doc.Add(new FacetField("Author", "Bob"));
+ doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Lisa"));
+ doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Lisa"));
+ doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Susan"));
+ doc.Add(new FacetField("Publish Date", "2012", "1", "7"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ doc = new Document();
+ doc.Add(new FacetField("Author", "Frank"));
+ doc.Add(new FacetField("Publish Date", "1999", "5", "5"));
+ indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+ } // Disposes indexWriter and taxoWriter
+ }
+
+ /// <summary>User runs a query and counts facets.</summary>
+ private IList<FacetResult> FacetsWithSearch()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ FacetsCollector fc = new FacetsCollector();
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+
+ // Retrieve results
+ IList<FacetResult> results = new List<FacetResult>();
+
+ // Count both "Publish Date" and "Author" dimensions
+ Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, fc);
+ results.Add(facets.GetTopChildren(10, "Author"));
+ results.Add(facets.GetTopChildren(10, "Publish Date"));
+
+ return results;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>User runs a query and counts facets only without collecting the matching documents.</summary>
+ private IList<FacetResult> FacetsOnly()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ FacetsCollector fc = new FacetsCollector();
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ searcher.Search(new MatchAllDocsQuery(), null /*Filter */, fc);
+
+ // Retrieve results
+ IList<FacetResult> results = new List<FacetResult>();
+
+ // Count both "Publish Date" and "Author" dimensions
+ Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, fc);
+
+ results.Add(facets.GetTopChildren(10, "Author"));
+ results.Add(facets.GetTopChildren(10, "Publish Date"));
+
+ return results;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>
+ /// User drills down on 'Publish Date/2010', and we
+ /// return facets for 'Author'
+ /// </summary>
+ private FacetResult DrillDown()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ // Passing no baseQuery means we drill down on all
+ // documents ("browse only"):
+ DrillDownQuery q = new DrillDownQuery(config);
+
+ // Now user drills down on Publish Date/2010:
+ q.Add("Publish Date", "2010");
+ FacetsCollector fc = new FacetsCollector();
+ FacetsCollector.Search(searcher, q, 10, fc);
+
+ // Retrieve results
+ Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, fc);
+ FacetResult result = facets.GetTopChildren(10, "Author");
+
+ return result;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>
+ /// User drills down on 'Publish Date/2010', and we
+ /// return facets for both 'Publish Date' and 'Author',
+ /// using DrillSideways.
+ /// </summary>
+ private IList<FacetResult> DrillSideways()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ using (TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ // Passing no baseQuery means we drill down on all
+ // documents ("browse only"):
+ DrillDownQuery q = new DrillDownQuery(config);
+
+ // Now user drills down on Publish Date/2010:
+ q.Add("Publish Date", "2010");
+
+ DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
+ DrillSideways.DrillSidewaysResult result = ds.Search(q, 10);
+
+ // Retrieve results
+ IList<FacetResult> facets = result.Facets.GetAllDims(10);
+
+ return facets;
+
+ } // Disposes indexReader and taxoReader
+ }
+
+ /// <summary>Runs the search example.</summary>
+ public IList<FacetResult> RunFacetOnly()
+ {
+ Index();
+ return FacetsOnly();
+ }
+
+ /// <summary>Runs the search example.</summary>
+ public IList<FacetResult> RunSearch()
+ {
+ Index();
+ return FacetsWithSearch();
+ }
+
+ /// <summary>Runs the drill-down example.</summary>
+ public FacetResult RunDrillDown()
+ {
+ Index();
+ return DrillDown();
+ }
+
+ /// <summary>Runs the drill-sideways example.</summary>
+ public IList<FacetResult> RunDrillSideways()
+ {
+ Index();
+ return DrillSideways();
+ }
+
+ /// <summary>Runs the search and drill-down examples and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Facet counting example:");
+ Console.WriteLine("-----------------------");
+ SimpleFacetsExample example1 = new SimpleFacetsExample();
+ IList<FacetResult> results1 = example1.RunFacetOnly();
+ Console.WriteLine("Author: " + results1[0]);
+ Console.WriteLine("Publish Date: " + results1[1]);
+
+ Console.WriteLine("Facet counting example (combined facets and search):");
+ Console.WriteLine("-----------------------");
+ SimpleFacetsExample example = new SimpleFacetsExample();
+ IList<FacetResult> results = example.RunSearch();
+ Console.WriteLine("Author: " + results[0]);
+ Console.WriteLine("Publish Date: " + results[1]);
+
+ Console.WriteLine();
+ Console.WriteLine("Facet drill-down example (Publish Date/2010):");
+ Console.WriteLine("---------------------------------------------");
+ Console.WriteLine("Author: " + example.RunDrillDown());
+
+ Console.WriteLine();
+ Console.WriteLine("Facet drill-sideways example (Publish Date/2010):");
+ Console.WriteLine("---------------------------------------------");
+ foreach (FacetResult result in example.RunDrillSideways())
+ {
+ Console.WriteLine(result);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Facet/SimpleSortedSetFacetsExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Facet/SimpleSortedSetFacetsExample.cs b/src/Lucene.Net.Demo/Facet/SimpleSortedSetFacetsExample.cs
new file mode 100644
index 0000000..b2d6da1
--- /dev/null
+++ b/src/Lucene.Net.Demo/Facet/SimpleSortedSetFacetsExample.cs
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+// Lucene.Net.Facet
+
+using Lucene.Net.Analysis.Core;
+using Lucene.Net.Documents;
+using Lucene.Net.Facet;
+using Lucene.Net.Facet.SortedSet;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Demo.Facet
+{
+ /// <summary>
+ /// Shows simple usage of faceted indexing and search
+ /// using <see cref="SortedSetDocValuesFacetField"/> and
+ /// <see cref="SortedSetDocValuesFacetCounts"/>.
+ /// </summary>
+ public class SimpleSortedSetFacetsExample
+ {
+ /// <summary>
+ /// Using a constant for all functionality related to a specific index
+ /// is the best strategy. This allows you to upgrade Lucene.Net first
+ /// and plan the upgrade of the index binary format for a later time.
+ /// Once the index is upgraded, you simply need to update the constant
+ /// version and redeploy your application.
+ /// </summary>
+ private const LuceneVersion EXAMPLE_VERSION = LuceneVersion.LUCENE_48;
+
+ private readonly Directory indexDir = new RAMDirectory();
+ private readonly FacetsConfig config = new FacetsConfig();
+
+ /// <summary>Build the example index.</summary>
+ private void Index()
+ {
+ using (IndexWriter indexWriter = new IndexWriter(indexDir,
+ new IndexWriterConfig(EXAMPLE_VERSION,
+ new WhitespaceAnalyzer(EXAMPLE_VERSION))))
+ {
+ Document doc = new Document();
+ doc.Add(new SortedSetDocValuesFacetField("Author", "Bob"));
+ doc.Add(new SortedSetDocValuesFacetField("Publish Year", "2010"));
+ indexWriter.AddDocument(config.Build(doc));
+
+ doc = new Document();
+ doc.Add(new SortedSetDocValuesFacetField("Author", "Lisa"));
+ doc.Add(new SortedSetDocValuesFacetField("Publish Year", "2010"));
+ indexWriter.AddDocument(config.Build(doc));
+
+ doc = new Document();
+ doc.Add(new SortedSetDocValuesFacetField("Author", "Lisa"));
+ doc.Add(new SortedSetDocValuesFacetField("Publish Year", "2012"));
+ indexWriter.AddDocument(config.Build(doc));
+
+ doc = new Document();
+ doc.Add(new SortedSetDocValuesFacetField("Author", "Susan"));
+ doc.Add(new SortedSetDocValuesFacetField("Publish Year", "2012"));
+ indexWriter.AddDocument(config.Build(doc));
+
+ doc = new Document();
+ doc.Add(new SortedSetDocValuesFacetField("Author", "Frank"));
+ doc.Add(new SortedSetDocValuesFacetField("Publish Year", "1999"));
+ indexWriter.AddDocument(config.Build(doc));
+
+ } // Disposes indexWriter
+ }
+
+ /// <summary>User runs a query and counts facets.</summary>
+ private IList<FacetResult> Search()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+ SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(indexReader);
+
+ // Aggregatses the facet counts
+ FacetsCollector fc = new FacetsCollector();
+
+ // MatchAllDocsQuery is for "browsing" (counts facets
+ // for all non-deleted docs in the index); normally
+ // you'd use a "normal" query:
+ FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+
+ // Retrieve results
+ Facets facets = new SortedSetDocValuesFacetCounts(state, fc);
+
+ IList<FacetResult> results = new List<FacetResult>();
+ results.Add(facets.GetTopChildren(10, "Author"));
+ results.Add(facets.GetTopChildren(10, "Publish Year"));
+
+ return results;
+
+ } // Disposes indexWriter
+ }
+
+ /// <summary>User drills down on 'Publish Year/2010'.</summary>
+ private FacetResult DrillDown()
+ {
+ using (DirectoryReader indexReader = DirectoryReader.Open(indexDir))
+ {
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+ SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(indexReader);
+
+ // Now user drills down on Publish Year/2010:
+ DrillDownQuery q = new DrillDownQuery(config);
+ q.Add("Publish Year", "2010");
+ FacetsCollector fc = new FacetsCollector();
+ FacetsCollector.Search(searcher, q, 10, fc);
+
+ // Retrieve results
+ Facets facets = new SortedSetDocValuesFacetCounts(state, fc);
+ FacetResult result = facets.GetTopChildren(10, "Author");
+
+ return result;
+
+ } // Disposes indexReader
+ }
+
+ /// <summary>Runs the search example.</summary>
+ public IList<FacetResult> RunSearch()
+ {
+ Index();
+ return Search();
+ }
+
+ /// <summary>Runs the drill-down example.</summary>
+ public FacetResult RunDrillDown()
+ {
+ Index();
+ return DrillDown();
+ }
+
+ /// <summary>Runs the search and drill-down examples and prints the results.</summary>
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Facet counting example:");
+ Console.WriteLine("-----------------------");
+ SimpleSortedSetFacetsExample example = new SimpleSortedSetFacetsExample();
+ IList<FacetResult> results = example.RunSearch();
+ Console.WriteLine("Author: " + results[0]);
+ Console.WriteLine("Publish Year: " + results[0]);
+
+ Console.WriteLine();
+ Console.WriteLine("Facet drill-down example (Publish Year/2010):");
+ Console.WriteLine("---------------------------------------------");
+ Console.WriteLine("Author: " + example.RunDrillDown());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/IndexFiles.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/IndexFiles.cs b/src/Lucene.Net.Demo/IndexFiles.cs
new file mode 100644
index 0000000..048821d
--- /dev/null
+++ b/src/Lucene.Net.Demo/IndexFiles.cs
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Add NuGet References:
+
+// Lucene.Net.Analysis.Common
+
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Standard;
+using Lucene.Net.Documents;
+using Lucene.Net.Index;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using System;
+using System.IO;
+using System.Text;
+
+namespace Lucene.Net.Demo
+{
+ /// <summary>
+ /// Index all text files under a directory.
+ /// <para/>
+ /// This is a command-line application demonstrating simple Lucene indexing.
+ /// Run it with no command-line arguments for usage information.
+ /// </summary>
+ public class IndexFiles
+ {
+ private IndexFiles() { }
+
+ /// <summary>Index all text files under a directory.</summary>
+ public static void Main(string[] args)
+ {
+ // The <CONSOLE_APP_NAME> should be the assembly name of the application
+ // this code is compiled into. In .NET Framework, it is the name of the EXE file.
+ // In .NET Core, you have the option of compiling this into either an EXE or a DLL
+ // (see https://docs.microsoft.com/en-us/dotnet/core/deploying/index).
+ // In the latter case, the <CONSOLE_APP_NAME> will be "dotnet <DLL_NAME>.dll".
+ string usage = "Usage: <CONSOLE_APP_NAME> <INDEX_DIRECTORY> <SOURCE_DIRECTORY> "
+ + "[-u|--update]\n\n"
+ + "This indexes the documents in <SOURCE_DIRECTORY>, creating a Lucene index"
+ + "in <INDEX_DIRECTORY> that can be searched with the search-files demo.";
+
+ // Validate required arguments are present.
+ // If not, show usage information.
+ if (args.Length < 2)
+ {
+ Console.WriteLine(usage);
+ Environment.Exit(1);
+ }
+ string indexPath = args[0];
+ string sourcePath = args[1];
+ bool create = true;
+
+ for (int i = 0; i < args.Length; i++)
+ {
+ if ("-u".Equals(args[i]) || "--update".Equals(args[i]))
+ {
+ create = false;
+ }
+ }
+
+ DirectoryInfo sourceDirectory = new DirectoryInfo(sourcePath);
+ if (!sourceDirectory.Exists)
+ {
+ Console.WriteLine("Source directory '" + sourcePath + "' does not exist, please check the path");
+ Environment.Exit(1);
+ }
+
+ DateTime start = DateTime.UtcNow;
+ try
+ {
+ Console.WriteLine("Indexing to directory '" + indexPath + "'...");
+
+ Store.Directory dir = FSDirectory.Open(indexPath);
+ // :Post-Release-Update-Version.LUCENE_XY:
+ Analyzer analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
+ IndexWriterConfig iwc = new IndexWriterConfig(LuceneVersion.LUCENE_48, analyzer);
+
+ if (create)
+ {
+ // Create a new index in the directory, removing any
+ // previously indexed documents:
+ iwc.OpenMode = OpenMode.CREATE;
+ }
+ else
+ {
+ // Add new documents to an existing index:
+ iwc.OpenMode = OpenMode.CREATE_OR_APPEND;
+ }
+
+ // Optional: for better indexing performance, if you
+ // are indexing many documents, increase the RAM
+ // buffer.
+ //
+ // iwc.RAMBufferSizeMB = 256.0;
+
+ using (IndexWriter writer = new IndexWriter(dir, iwc))
+ {
+ IndexDocs(writer, sourceDirectory);
+
+ // NOTE: if you want to maximize search performance,
+ // you can optionally call forceMerge here. This can be
+ // a terribly costly operation, so generally it's only
+ // worth it when your index is relatively static (ie
+ // you're done adding documents to it):
+ //
+ // writer.ForceMerge(1);
+ }
+
+ DateTime end = DateTime.UtcNow;
+ Console.WriteLine((end - start).TotalMilliseconds + " total milliseconds");
+ }
+ catch (IOException e)
+ {
+ Console.WriteLine(" caught a " + e.GetType() +
+ "\n with message: " + e.Message);
+ }
+ }
+
+ /// <summary>
+ /// Recurses over files and directories found under the
+ /// given directory and indexes each file.<para/>
+ ///
+ /// NOTE: This method indexes one document per input file.
+ /// This is slow. For good throughput, put multiple documents
+ /// into your input file(s).
+ /// </summary>
+ /// <param name="writer">
+ /// <see cref="IndexWriter"/> to the index where the given
+ /// file/dir info will be stored
+ /// </param>
+ /// <param name="directoryInfo">
+ /// The directory to recurse into to find files to index.
+ /// </param>
+ /// <exception cref="IOException">
+ /// If there is a low-level I/O error.
+ /// </exception>
+ internal static void IndexDocs(IndexWriter writer, DirectoryInfo directoryInfo)
+ {
+ foreach (var dirInfo in directoryInfo.GetDirectories())
+ {
+ IndexDocs(writer, dirInfo);
+ }
+ foreach (var fileInfo in directoryInfo.GetFiles())
+ {
+ IndexDocs(writer, fileInfo);
+ }
+ }
+
+ /// <summary>
+ /// Indexes the given file using the given writer.<para/>
+ /// </summary>
+ /// <param name="writer">
+ /// <see cref="IndexWriter"/> to the index where the given
+ /// file info will be stored.
+ /// </param>
+ /// <param name="file">
+ /// The file to index.
+ /// </param>
+ /// <exception cref="IOException">
+ /// If there is a low-level I/O error.
+ /// </exception>
+ internal static void IndexDocs(IndexWriter writer, FileInfo file)
+ {
+ using (FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
+ {
+ // make a new, empty document
+ Document doc = new Document();
+
+ // Add the path of the file as a field named "path". Use a
+ // field that is indexed (i.e. searchable), but don't tokenize
+ // the field into separate words and don't index term frequency
+ // or positional information:
+ Field pathField = new StringField("path", file.FullName, Field.Store.YES);
+ doc.Add(pathField);
+
+ // Add the last modified date of the file a field named "modified".
+ // Use a LongField that is indexed (i.e. efficiently filterable with
+ // NumericRangeFilter). This indexes to milli-second resolution, which
+ // is often too fine. You could instead create a number based on
+ // year/month/day/hour/minutes/seconds, down the resolution you require.
+ // For example the long value 2011021714 would mean
+ // February 17, 2011, 2-3 PM.
+ doc.Add(new Int64Field("modified", file.LastWriteTimeUtc.Ticks, Field.Store.NO));
+
+ // Add the contents of the file to a field named "contents". Specify a Reader,
+ // so that the text of the file is tokenized and indexed, but not stored.
+ // Note that FileReader expects the file to be in UTF-8 encoding.
+ // If that's not the case searching for special characters will fail.
+ doc.Add(new TextField("contents", new StreamReader(fs, Encoding.UTF8)));
+
+ if (writer.Config.OpenMode == OpenMode.CREATE)
+ {
+ // New index, so we just add the document (no old document can be there):
+ Console.WriteLine("adding " + file);
+ writer.AddDocument(doc);
+ }
+ else
+ {
+ // Existing index (an old copy of this document may have been indexed) so
+ // we use updateDocument instead to replace the old one matching the exact
+ // path, if present:
+ Console.WriteLine("updating " + file);
+ writer.UpdateDocument(new Term("path", file.FullName), doc);
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj b/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj
new file mode 100644
index 0000000..eb01c86
--- /dev/null
+++ b/src/Lucene.Net.Demo/Lucene.Net.Demo.csproj
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{D1661154-8F5B-499A-8B2D-04B8A67F4232}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Lucene.Net.Demo</RootNamespace>
+ <AssemblyName>Lucene.Net.Demo</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup>
+ <DefineConstants>$(DefineConstants);FEATURE_SERIALIZABLE</DefineConstants>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Facet\AssociationsFacetsExample.cs" />
+ <Compile Include="Facet\DistanceFacetsExample.cs" />
+ <Compile Include="Facet\ExpressionAggregationFacetsExample.cs" />
+ <Compile Include="Facet\MultiCategoryListsFacetsExample.cs" />
+ <Compile Include="Facet\RangeFacetsExample.cs" />
+ <Compile Include="Facet\SimpleFacetsExample.cs" />
+ <Compile Include="Facet\SimpleSortedSetFacetsExample.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="..\CommonAssemblyInfo.cs">
+ <Link>Properties\CommonAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="IndexFiles.cs" />
+ <Compile Include="SearchFiles.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Lucene.Net.Analysis.Common\Lucene.Net.Analysis.Common.csproj">
+ <Project>{4add0bbc-b900-4715-9526-d871de8eea64}</Project>
+ <Name>Lucene.Net.Analysis.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Lucene.Net.Expressions\Lucene.Net.Expressions.csproj">
+ <Project>{dc83004c-183a-4e1a-abea-4fe95b4bc079}</Project>
+ <Name>Lucene.Net.Expressions</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Lucene.Net.Facet\Lucene.Net.Facet.csproj">
+ <Project>{48f7884a-9454-4e88-8413-9d35992cb440}</Project>
+ <Name>Lucene.Net.Facet</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Lucene.Net.Queries\Lucene.Net.Queries.csproj">
+ <Project>{69d7956c-c2cc-4708-b399-a188fec384c4}</Project>
+ <Name>Lucene.Net.Queries</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Lucene.Net.QueryParser\Lucene.Net.QueryParser.csproj">
+ <Project>{949ba34b-6ae6-4ce3-b578-61e13e4d76bf}</Project>
+ <Name>Lucene.Net.QueryParser</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Lucene.Net\Lucene.Net.csproj">
+ <Project>{5d4ad9be-1ffb-41ab-9943-25737971bf57}</Project>
+ <Name>Lucene.Net</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Lucene.Net.Demo.project.json" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Lucene.Net.Demo.project.json
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Lucene.Net.Demo.project.json b/src/Lucene.Net.Demo/Lucene.Net.Demo.project.json
new file mode 100644
index 0000000..fb9054b
--- /dev/null
+++ b/src/Lucene.Net.Demo/Lucene.Net.Demo.project.json
@@ -0,0 +1,8 @@
+{
+ "runtimes": {
+ "win":{}
+ },
+ "frameworks": {
+ "net451": {}
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/775df654/src/Lucene.Net.Demo/Lucene.Net.Demo.xproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Demo/Lucene.Net.Demo.xproj b/src/Lucene.Net.Demo/Lucene.Net.Demo.xproj
new file mode 100644
index 0000000..82e3ee2
--- /dev/null
+++ b/src/Lucene.Net.Demo/Lucene.Net.Demo.xproj
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>4bcd7980-0cf4-4da0-b069-f555a41cb44d</ProjectGuid>
+ <RootNamespace>Lucene.Net.Demo</RootNamespace>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project>