mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Adding faceted search capabilities
--HG-- branch : 1.x
This commit is contained in:
@@ -639,5 +639,24 @@ namespace Orchard.Tests.Modules.Indexing {
|
||||
.WithField("field3", 3).Mandatory().AsFilter()
|
||||
.Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldReturnFacetedResults() {
|
||||
_provider.CreateIndex("default");
|
||||
_provider.Store("default", _provider.New(1).Add("body", "michael is in the kitchen").Analyze());
|
||||
_provider.Store("default", _provider.New(2).Add("body", "michael has a cousin named michel").Analyze());
|
||||
_provider.Store("default", _provider.New(3).Add("body", "speak inside the mic").Analyze());
|
||||
_provider.Store("default", _provider.New(4).Add("body", "a dog is pursuing a cat").Analyze());
|
||||
_provider.Store("default", _provider.New(5).Add("body", "michael speaks to elephants").Analyze());
|
||||
|
||||
var michael = SearchBuilder.WithField("body", "michael").GetBits();
|
||||
var speak = SearchBuilder.WithField("body", "speak").GetBits();
|
||||
Assert.That(michael.Count(), Is.EqualTo(3));
|
||||
Assert.That(speak.Count(), Is.EqualTo(2));
|
||||
|
||||
Assert.That(speak.And(michael).Count(), Is.EqualTo(1));
|
||||
Assert.That(speak.Or(michael).Count(), Is.EqualTo(4));
|
||||
Assert.That(speak.Xor(michael).Count(), Is.EqualTo(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,10 @@
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>4.0</OldToolsVersion>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -66,6 +70,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\LuceneIndexProvider.cs" />
|
||||
<Compile Include="Services\LuceneSearchBuilder.cs" />
|
||||
<Compile Include="Services\SearchBits.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Module.txt" />
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -6,6 +7,7 @@ using Lucene.Models;
|
||||
using Lucene.Net.Index;
|
||||
using Lucene.Net.Search;
|
||||
using Lucene.Net.Store;
|
||||
using Lucene.Net.Util;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Logging;
|
||||
using Lucene.Net.Documents;
|
||||
@@ -355,6 +357,30 @@ namespace Lucene.Services {
|
||||
|
||||
}
|
||||
|
||||
public ISearchBits GetBits() {
|
||||
var query = CreateQuery();
|
||||
IndexSearcher searcher;
|
||||
|
||||
try {
|
||||
searcher = new IndexSearcher(_directory, true);
|
||||
}
|
||||
catch {
|
||||
// index might not exist if it has been rebuilt
|
||||
Logger.Information("Attempt to read a none existing index");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var filter = new QueryWrapperFilter(query);
|
||||
var bits = filter.GetDocIdSet(searcher.GetIndexReader());
|
||||
var disi = new OpenBitSetDISI(bits.Iterator(), searcher.MaxDoc());
|
||||
return new SearchBits(disi);
|
||||
}
|
||||
finally {
|
||||
searcher.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public ISearchHit Get(int documentId) {
|
||||
var query = new TermQuery(new Term("id", documentId.ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
|
43
src/Orchard.Web/Modules/Lucene/Services/SearchBits.cs
Normal file
43
src/Orchard.Web/Modules/Lucene/Services/SearchBits.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using Lucene.Net.Util;
|
||||
using Orchard.Indexing;
|
||||
|
||||
namespace Lucene.Services {
|
||||
public class SearchBits : ISearchBits {
|
||||
internal readonly OpenBitSet _openBitSet;
|
||||
|
||||
public SearchBits(OpenBitSet openBitSet) {
|
||||
_openBitSet = openBitSet;
|
||||
}
|
||||
|
||||
public ISearchBits And(ISearchBits other) {
|
||||
return Apply(other, (x, y) => x.And(y));
|
||||
}
|
||||
|
||||
public ISearchBits Or(ISearchBits other) {
|
||||
return Apply(other, (x, y) => x.Or(y));
|
||||
}
|
||||
|
||||
public ISearchBits Xor(ISearchBits other) {
|
||||
return Apply(other, (x, y) => x.Xor(y));
|
||||
}
|
||||
|
||||
public long Count() {
|
||||
return _openBitSet.Cardinality();
|
||||
}
|
||||
|
||||
private ISearchBits Apply(ISearchBits other, Action<OpenBitSet, OpenBitSet> operation) {
|
||||
var bitset = (OpenBitSet)_openBitSet.Clone();
|
||||
var otherBitSet = other as SearchBits;
|
||||
|
||||
if (otherBitSet == null) {
|
||||
throw new InvalidOperationException("The other bitset must be of type OpenBitSet");
|
||||
}
|
||||
|
||||
operation(bitset, otherBitSet._openBitSet);
|
||||
|
||||
return new SearchBits(bitset);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -57,6 +57,7 @@ namespace Orchard.Indexing {
|
||||
ISearchBuilder Slice(int skip, int count);
|
||||
IEnumerable<ISearchHit> Search();
|
||||
ISearchHit Get(int documentId);
|
||||
ISearchBits GetBits();
|
||||
int Count();
|
||||
|
||||
}
|
||||
|
@@ -127,6 +127,11 @@ namespace Orchard.Indexing {
|
||||
public ISearchHit Get(int documentId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ISearchBits GetBits() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int Count() {
|
||||
return 0;
|
||||
}
|
||||
|
@@ -238,6 +238,7 @@
|
||||
<Compile Include="FileSystems\LockFile\LockFile.cs" />
|
||||
<Compile Include="FileSystems\LockFile\DefaultLockFileManager.cs" />
|
||||
<Compile Include="FileSystems\Media\FileSystemStorageProvider.cs" />
|
||||
<Compile Include="Indexing\ISearchBits.cs" />
|
||||
<Compile Include="Localization\Services\CurrentCultureWorkContext.cs" />
|
||||
<Compile Include="Localization\Services\DefaultLocalizedStringManager.cs" />
|
||||
<Compile Include="Localization\Services\ILocalizedStringManager.cs" />
|
||||
|
Reference in New Issue
Block a user