温馨提示:代码在线浏览功能只能做为源码浏览参考,如果想更进一步了解该代码请下载:LiveBlog v1.0测试版源码
当前文件:
LiveBlog/LiveBlog.Core/Search.cs,打开代码结构图
LiveBlog/LiveBlog.Core/Search.cs,打开代码结构图1Using#region Using 2
3
using System; 4
using System.IO; 5
using System.Text; 6
using System.Web; 7
using System.Collections.ObjectModel; 8
using System.Collections.Generic; 9
using System.Collections.Specialized; 10
using LiveBlog.Core; 11
using System.Text.RegularExpressions; 12
13
#endregion 14
15
namespace LiveBlog.Core 16
...{ 17
/**//// <summary> 18
/// Searches the post collection and returns a result based on a search term. 19
/// <remarks>It is used for related posts and the in-site search feature.</remarks> 20
/// </summary> 21
public static class Search 22
...{ 23
24
static Search() 25
...{ 26
BuildCatalog(); 27
Post.Saved += new EventHandler<SavedEventArgs>(Post_Saved); 28
Page.Saved += new EventHandler<SavedEventArgs>(Page_Saved); 29
BlogSettings.Changed += delegate ...{ BuildCatalog(); }; 30
Post.CommentAdded += new EventHandler<EventArgs>(Post_CommentAdded); 31
Post.CommentRemoved += delegate ...{ BuildCatalog(); }; 32
Comment.Approved += new EventHandler<EventArgs>(Post_CommentAdded); 33
} 34
35
Event handlers#region Event handlers 36
37
/**//// <summary> 38
/// Adds a post to the catalog when it is added. 39
/// </summary> 40
private static void Post_Saved(object sender, SavedEventArgs e) 41
...{ 42
lock (_SyncRoot) 43
...{ 44
if (e.Action == SaveAction.Insert) 45
...{ 46
AddItem(sender as Post); 47
} 48
else 49
...{ 50
BuildCatalog(); 51
} 52
} 53
} 54
55
private static void Page_Saved(object sender, SavedEventArgs e) 56
...{ 57
lock (_SyncRoot) 58
...{ 59
if (e.Action == SaveAction.Insert) 60
...{ 61
AddItem(sender as Page); 62
} 63
else 64
...{ 65
BuildCatalog(); 66
} 67
} 68
} 69
70
static void Post_CommentAdded(object sender, EventArgs e) 71
...{ 72
if (BlogSettings.Instance.EnableCommentSearch) 73
...{ 74
Comment comment = (Comment)sender; 75
if (comment.IsVisible) 76
AddItem(comment); 77
} 78
} 79
80
#endregion 81
82
Search#region Search 83
84
/**//// <summary> 85
/// Searches all the posts and returns a ranked result set. 86
/// </summary> 87
/// <param name="searchTerm">The term to search for</param> 88
/// <param name="includeComments">True to include a post's comments and their authors in search</param> 89
public static List<IPublishable> Hits(string searchTerm, bool includeComments) 90
...{ 91
lock (_SyncRoot) 92
...{ 93
List<Result> results = BuildResultSet(searchTerm, includeComments); 94
List<IPublishable> items = results.ConvertAll(new Converter<Result, IPublishable>(ResultToPost)); 95
results.Clear(); 96
OnSearcing(searchTerm); 97
return items; 98
} 99
} 100
101
/**//// <summary> 102
/// Returns a list of posts that is related to the specified post. 103
/// </summary> 104
public static List<IPublishable> FindRelatedItems(IPublishable post) 105
...{ 106
string term = post.Title; 107
108
foreach (Category cat in post.Categories) 109
...{ 110
term += " " + cat.Title; 111
} 112
113
term = CleanContent(term, false); 114
return Hits(term, false); 115
} 116
117
/**//// <summary> 118
/// Builds the results set and ranks it. 119
/// </summary> 120
private static List<Result> BuildResultSet(string searchTerm, bool includeComments) 121
...{ 122
List<Result> results = new List<Result>(); 123
string term = CleanContent(searchTerm.ToLowerInvariant().Trim(), false); 124
string[] terms = term.Split(new char[] ...{ ' ' }, StringSplitOptions.RemoveEmptyEntries); 125
string regex = string.Format(System.Globalization.CultureInfo.InvariantCulture, "({0})", string.Join("|", terms)); 126
127
foreach (Entry entry in _Catalog) 128
...{ 129
Result result = new Result(); 130
if (!(entry.Item is Comment)) 131
...{ 132
int titleMatches = Regex.Matches(entry.Title, regex).Count; 133
result.Rank = titleMatches * 20; 134
135
int postMatches = Regex.Matches(entry.Content, regex).Count; 136
result.Rank += postMatches; 137
} 138
else if (includeComments) 139
...{ 140
int commentMatches = Regex.Matches(entry.Content + entry.Title, regex).Count; 141
result.Rank += commentMatches; 142
} 143
144
if (result.Rank > 0) 145
...{ 146
result.Item = entry.Item; 147
results.Add(result); 148
} 149
} 150
151
results.Sort(); 152
return results; 153
} 154
155
/**//// <summary> 156
/// A converter delegate used for converting Results to Posts. 157
/// </summary> 158
private static IPublishable ResultToPost(Result result) 159
...{ 160
return result.Item; 161
} 162
163
#endregion 164
165
Properties and private fields#region Properties and private fields 166
167
private readonly static object _SyncRoot = new object(); 168
private readonly static Regex _StripHtml = new Regex("<[^>]*>", RegexOptions.Compiled); 169
private readonly static StringCollection _StopWords = GetStopWords(); 170
private static Collection<Entry> _Catalog = new Collection<Entry>(); 171
172
#endregion 173
174
BuildCatalog#region BuildCatalog 175
176
private static void BuildCatalog() 177
...{ 178
OnIndexBuilding(); 179
180
lock (_SyncRoot) 181
...{ 182
_Catalog.Clear(); 183
foreach (Post post in Post.Posts) 184
...{ 185
if (!post.IsVisible) 186
continue; 187
188
AddItem(post); 189
if (BlogSettings.Instance.EnableCommentSearch) 190
...{ 191
foreach (Comment comment in post.Comments) 192
...{ 193
if (comment.IsVisible) 194
AddItem(comment); 195
} 196
} 197
} 198
199
foreach (Page page in Page.Pages) 200
...{ 201
if (page.IsVisible) 202
AddItem(page); 203
} 204
} 205
206
OnIndexBuild(); 207
} 208
209
/**//// <summary> 210
/// Adds an IPublishable item to the search catalog. 211
/// That will make it immediately searchable. 212
/// </summary> 213
public static void AddItem(IPublishable item) 214
...{ 215
Entry entry = new Entry(); 216
entry.Item = item; 217
entry.Title = CleanContent(item.Title, false); 218
entry.Content = HttpUtility.HtmlDecode(CleanContent(item.Content, true)); 219
if (item is Comment) 220
...{ 221
entry.Content += HttpUtility.HtmlDecode(CleanContent(item.Author, false)); 222
} 223
_Catalog.Add(entry); 224
} 225
226
/**//// <summary> 227
/// Removes stop words and HTML from the specified string. 228
/// </summary> 229
private static string CleanContent(string content, bool removeHtml) 230
...{ 231
if (removeHtml) 232
content = _StripHtml.Replace(content, string.Empty); 233
234
content = content 235
.Replace("\\", string.Empty) 236
.Replace("|", string.Empty) 237
.Replace("(", string.Empty) 238
.Replace(")", string.Empty) 239
.Replace("[", string.Empty) 240
.Replace("]", string.Empty) 241
.Replace("+", string.Empty); 242
243
string[] words = content.Split(new char[] ...{ ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); 244
StringBuilder sb = new StringBuilder(); 245
for (int i = 0; i < words.Length; i++) 246
...{ 247
string word = words[i].ToLowerInvariant().Trim(); 248
if (word.Length > 1 && !_StopWords.Contains(word)) 249
sb.Append(word + " "); 250
} 251
252
return sb.ToString(); 253
} 254
255
/**//// <summary> 256
/// Retrieves the stop words from the stopwords.txt file located in App_Data. 257
/// </summary> 258
private static StringCollection GetStopWords() 259
...{ 260
using (StreamReader reader = new StreamReader(System.Web.HttpContext.Current.Server.MapPath(BlogSettings.Instance.StorageLocation) + "stopwords.txt")) 261
...{ 262
string file = reader.ReadToEnd(); 263
string[] words = file.Split(new char[] ...{ '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); 264
265
StringCollection col = new StringCollection(); 266
col.AddRange(words); 267
268
return col; 269
} 270
} 271
272
#endregion 273
274




