Skip to content

Commit 05321c0

Browse files
author
oposumi
committed
Add project files.
1 parent f40a4c8 commit 05321c0

File tree

11 files changed

+342
-0
lines changed

11 files changed

+342
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace LuceneSearchExample.Services.Models
6+
{
7+
public class BuildIndexRequest
8+
{
9+
public IEnumerable<User> Users;
10+
}
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
</Project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace LuceneSearchExample.Services.Models
6+
{
7+
public class SearchRequest
8+
{
9+
public string Query { get; set; }
10+
}
11+
12+
public class SearchResponse
13+
{
14+
public SearchResponse() => Users = new List<User>();
15+
public int TotalCount{ get; set; }
16+
public IList<User> Users { get; set; }
17+
}
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace LuceneSearchExample.Services.Models
6+
{
7+
public class User
8+
{
9+
public int UserId { get; set; }
10+
public string FirstName { get; set; }
11+
public string LastName { get; set; }
12+
public int Age { get; set; }
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using LuceneSearchExample.Services.Concrete;
2+
using LuceneSearchExample.Services.Models;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text;
6+
7+
namespace LuceneSearchExample.Services.Abstract
8+
{
9+
public interface ISearchService
10+
{
11+
void BuildIndex(BuildIndexRequest request);
12+
SearchResponse Search(SearchRequest request);
13+
}
14+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using Lucene.Net.Analysis;
2+
using Lucene.Net.Analysis.Core;
3+
using Lucene.Net.Analysis.Miscellaneous;
4+
using Lucene.Net.Analysis.Standard;
5+
using Lucene.Net.Documents;
6+
using Lucene.Net.Index;
7+
using Lucene.Net.QueryParsers.Classic;
8+
using Lucene.Net.Search;
9+
using Lucene.Net.Store;
10+
using Lucene.Net.Util;
11+
using LuceneSearchExample.Services.Models;
12+
using System;
13+
using System.Collections.Generic;
14+
15+
namespace LuceneSearchExample.Services.Concrete
16+
{
17+
internal class Index : IDisposable
18+
{
19+
private const LuceneVersion MATCH_LUCENE_VERSION = LuceneVersion.LUCENE_48;
20+
private const int SNIPPET_LENGTH = 100;
21+
private readonly IndexWriter writer;
22+
private readonly Analyzer analyzer;
23+
private readonly QueryParser queryParser;
24+
private readonly SearcherManager searchManager;
25+
26+
public Index(string indexPath)
27+
{
28+
analyzer = SetupAnalyzer();
29+
queryParser = SetupQueryParser(analyzer);
30+
writer = new IndexWriter(FSDirectory.Open(indexPath), new IndexWriterConfig(MATCH_LUCENE_VERSION, analyzer));
31+
searchManager = new SearcherManager(writer, true, null);
32+
}
33+
34+
private Analyzer SetupAnalyzer()
35+
{
36+
return Analyzer.NewAnonymous((field, reader) =>
37+
{
38+
var tokenizer = new StandardTokenizer(MATCH_LUCENE_VERSION, reader);
39+
TokenStream tokenStream = new StandardFilter(MATCH_LUCENE_VERSION, tokenizer);
40+
tokenStream = new ASCIIFoldingFilter(tokenStream);
41+
tokenStream = new LowerCaseFilter(MATCH_LUCENE_VERSION, tokenStream);
42+
tokenStream = new StopFilter(MATCH_LUCENE_VERSION, tokenStream, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
43+
return new TokenStreamComponents(tokenizer, tokenStream);
44+
});
45+
}
46+
47+
private QueryParser SetupQueryParser(Analyzer analyzer)
48+
{
49+
return new MultiFieldQueryParser(
50+
MATCH_LUCENE_VERSION,
51+
new[] { "firstname", "lastname", "age" },
52+
analyzer
53+
);
54+
}
55+
56+
public void Build(IEnumerable<User> users)
57+
{
58+
if (users == null)
59+
{
60+
throw new ArgumentNullException();
61+
}
62+
foreach (var user in users)
63+
{
64+
writer.UpdateDocument(new Term("id", user.UserId.ToString()), BuildDocument(user));
65+
66+
}
67+
writer.Flush(true, true);
68+
writer.Commit();
69+
}
70+
71+
private Document BuildDocument(User user)
72+
{
73+
Document doc = new Document
74+
{
75+
new StoredField("userid", user.UserId),
76+
new TextField("firstname", user.FirstName, Field.Store.YES),
77+
new TextField("lastname", user.LastName, Field.Store.YES),
78+
new StringField("age", user.Age.ToString(), Field.Store.YES)
79+
};
80+
return doc;
81+
}
82+
83+
public SearchResponse Search(string queryString)
84+
{
85+
int resultsPerPage = 10;
86+
Query query = BuildQuery(queryString);
87+
searchManager.MaybeRefreshBlocking();
88+
IndexSearcher searcher = searchManager.Acquire();
89+
try
90+
{
91+
TopDocs topdDocs = searcher.Search(query, resultsPerPage);
92+
return CompileResults(searcher, topdDocs);
93+
}
94+
finally
95+
{
96+
searchManager.Release(searcher);
97+
searcher = null;
98+
}
99+
}
100+
101+
private SearchResponse CompileResults(IndexSearcher searcher, TopDocs topdDocs)
102+
{
103+
var searchResults = new SearchResponse() { TotalCount = topdDocs.TotalHits };
104+
foreach (var result in topdDocs.ScoreDocs)
105+
{
106+
var document = searcher.Doc(result.Doc);
107+
var searchResult = new User
108+
{
109+
Age = Convert.ToInt32(document.GetField("age")?.GetStringValue()),
110+
FirstName = document.GetField("firstname")?.GetStringValue(),
111+
UserId = Convert.ToInt32(document.GetField("userid")?.GetStringValue()),
112+
LastName = document.GetField("lastname")?.GetStringValue()
113+
};
114+
searchResults.Users.Add(searchResult);
115+
}
116+
return searchResults;
117+
}
118+
119+
private Query BuildQuery(string queryString)
120+
{
121+
return queryParser.Parse(Sanitize(queryString));
122+
}
123+
124+
private string Sanitize(string queryString)
125+
{
126+
string[] removed = { "*", "?", "%", "+" };
127+
string[] spaces = { "-" };
128+
foreach (var r in removed)
129+
{
130+
queryString = queryString.Replace(r, string.Empty);
131+
}
132+
foreach (var s in spaces)
133+
{
134+
queryString = queryString.Replace(s, " ");
135+
}
136+
return queryString;
137+
}
138+
139+
public void Dispose()
140+
{
141+
searchManager?.Dispose();
142+
analyzer?.Dispose();
143+
writer?.Dispose();
144+
}
145+
}
146+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using LuceneSearchExample.Services.Abstract;
2+
using LuceneSearchExample.Services.Models;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text;
6+
7+
namespace LuceneSearchExample.Services.Concrete
8+
{
9+
public class SearchService : ISearchService
10+
{
11+
private readonly Index index;
12+
13+
public SearchService(string indexDirectory)
14+
{
15+
index = new Index(indexDirectory);
16+
}
17+
18+
public void BuildIndex(BuildIndexRequest request)
19+
{
20+
index.Build(request.Users);
21+
}
22+
23+
public SearchResponse Search(SearchRequest request) => index.Search(request.Query);
24+
}
25+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Folder Include="Abstract\" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Lucene.Net" Version="4.8.0-beta00004" />
13+
<PackageReference Include="Lucene.Net.QueryParser" Version="4.8.0-beta00004" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\LuceneSearchExample.Services.Models\LuceneSearchExample.Services.Models.csproj" />
18+
</ItemGroup>
19+
20+
</Project>

LuceneSearchExample.sln

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.26730.12
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuceneSearchExample", "LuceneSearchExample\LuceneSearchExample.csproj", "{A15F3E42-9E93-4849-A013-252809D94439}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuceneSearchExample.Services", "LuceneSearchExample.Services\LuceneSearchExample.Services.csproj", "{F477A264-92A5-46AC-AB9E-C7A97B9B645A}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuceneSearchExample.Services.Models", "LuceneSearchExample.Services.Models\LuceneSearchExample.Services.Models.csproj", "{FDFCC9F4-B2C8-4C7E-A8DA-DD9ECE0D326C}"
11+
EndProject
12+
Global
13+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
14+
Debug|Any CPU = Debug|Any CPU
15+
Release|Any CPU = Release|Any CPU
16+
EndGlobalSection
17+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
18+
{A15F3E42-9E93-4849-A013-252809D94439}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19+
{A15F3E42-9E93-4849-A013-252809D94439}.Debug|Any CPU.Build.0 = Debug|Any CPU
20+
{A15F3E42-9E93-4849-A013-252809D94439}.Release|Any CPU.ActiveCfg = Release|Any CPU
21+
{A15F3E42-9E93-4849-A013-252809D94439}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{F477A264-92A5-46AC-AB9E-C7A97B9B645A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{F477A264-92A5-46AC-AB9E-C7A97B9B645A}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{F477A264-92A5-46AC-AB9E-C7A97B9B645A}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{F477A264-92A5-46AC-AB9E-C7A97B9B645A}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{FDFCC9F4-B2C8-4C7E-A8DA-DD9ECE0D326C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{FDFCC9F4-B2C8-4C7E-A8DA-DD9ECE0D326C}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{FDFCC9F4-B2C8-4C7E-A8DA-DD9ECE0D326C}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{FDFCC9F4-B2C8-4C7E-A8DA-DD9ECE0D326C}.Release|Any CPU.Build.0 = Release|Any CPU
30+
EndGlobalSection
31+
GlobalSection(SolutionProperties) = preSolution
32+
HideSolutionNode = FALSE
33+
EndGlobalSection
34+
GlobalSection(ExtensibilityGlobals) = postSolution
35+
SolutionGuid = {BEC39F92-05D6-42EF-9A6A-54E074A9D688}
36+
EndGlobalSection
37+
EndGlobal
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp2.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<ProjectReference Include="..\LuceneSearchExample.Services\LuceneSearchExample.Services.csproj" />
10+
</ItemGroup>
11+
12+
</Project>

LuceneSearchExample/Program.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using LuceneSearchExample.Services.Concrete;
2+
using LuceneSearchExample.Services.Models;
3+
using System;
4+
using System.Collections.Generic;
5+
6+
namespace LuceneSearchExample
7+
{
8+
class Program
9+
{
10+
static void Main(string[] args)
11+
{
12+
var searchService = new SearchService(@"D:\index");
13+
14+
searchService.BuildIndex(new BuildIndexRequest()
15+
{
16+
Users = new List<User>()
17+
{
18+
new User { UserId =1 , Age = 27 , FirstName = "Dani", LastName = "Daniels" },
19+
new User { UserId =1 , Age = 29 , FirstName = "Sasha", LastName = "Grey" },
20+
new User { UserId =1 , Age = 31 , FirstName = "Nicole", LastName = "Aniston" },
21+
new User { UserId =1 , Age = 28 , FirstName = "Tori", LastName = "Black" },
22+
}
23+
});
24+
25+
26+
var searchRequest = new SearchRequest()
27+
{
28+
Query = "Daniels"
29+
};
30+
var searchResponse = searchService.Search(searchRequest);
31+
foreach (var item in searchResponse.Users)
32+
{
33+
Console.WriteLine($"{item.UserId} - {item.FirstName} - {item.LastName} - {item.Age}");
34+
}
35+
Console.ReadLine();
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)