7
7
using ServiceStack . Text ;
8
8
using static ServiceStack . Text . JsonSerializer ;
9
9
using ServiceStack . OrmLite ;
10
+ using ServiceStack . OrmLite . PostgreSQL ;
10
11
11
12
namespace DatabaseService
12
13
{
@@ -19,33 +20,48 @@ public static class Database
19
20
static Database ( )
20
21
{
21
22
dbFactory = new OrmLiteConnectionFactory ( ConnectionString , PostgreSqlDialect . Provider ) ;
23
+ bool empty ;
22
24
using ( var db = dbFactory . Open ( ) )
23
25
{
24
- if ( db . CreateTableIfNotExists < NewsArticle > ( ) )
26
+ empty = db . CreateTableIfNotExists < NewsArticle > ( ) ;
27
+ if ( empty )
25
28
{
26
- List < NewsArticle > News = LoadFromFile ( ) ;
27
- News = News . OrderBy ( art => art . Date ) . ToList ( ) ;
28
- foreach ( NewsArticle article in News )
29
- {
30
- db . Insert ( article ) ;
31
- }
32
- }
33
- SaveToFile ( ) ;
34
- db . ExecuteSql ( @"
29
+ db . ExecuteSql ( @"
35
30
DROP TABLE IF EXISTS text_analysis
36
31
;" ) ;
37
- db . ExecuteSql ( @"
32
+ db . ExecuteSql ( @"
38
33
CREATE TABLE text_analysis(
39
34
id SERIAL PRIMARY KEY,
40
- article_id SERIAL REFERENCES news_article(id),
35
+ article_id SERIAL REFERENCES news_article(id) ON DELETE CASCADE ,
41
36
tsvec tsvector
42
37
);" ) ;
38
+ }
43
39
db . ExecuteSql ( @"
44
- INSERT INTO text_analysis (article_id, tsvec)
45
- SELECT id, to_tsvector(text)
46
- FROM news_article
40
+ CREATE INDEX IF NOT EXISTS url_index ON news_article (url)
47
41
;" ) ;
42
+ //db.CreateIndex<NewsArticle>(art => art.URL);
43
+ NewsArticle egg = new NewsArticle (
44
+ "tg: @Rigorich" ,
45
+ "-" ,
46
+ "Author" ,
47
+ "Ãðèøàåâ Íèêèòà Ãðèãîðüåâè÷" ,
48
+ System . Data . SqlTypes . SqlDateTime . MinValue . Value
49
+ ) ;
50
+ if ( ! db . Exists < NewsArticle > ( art => art . URL == egg . URL ) )
51
+ {
52
+ db . Insert ( egg ) ;
53
+ }
54
+ }
55
+ if ( empty )
56
+ {
57
+ List < NewsArticle > News = LoadFromFile ( ) ;
58
+ News = News . OrderBy ( art => art . Date ) . ToList ( ) ;
59
+ foreach ( NewsArticle article in News )
60
+ {
61
+ Add ( article ) ;
62
+ }
48
63
}
64
+ SaveToFile ( ) ;
49
65
}
50
66
static List < NewsArticle > LoadFromFile ( )
51
67
{
@@ -90,12 +106,11 @@ public static void Add(NewsArticle article)
90
106
if ( ! db . Exists < NewsArticle > ( m => m . URL == article . URL && m . Text == article . Text ) )
91
107
{
92
108
db . Insert ( article ) ;
93
- long articleId = db . LastInsertId ( ) ;
94
109
db . ExecuteSql ( @"
95
110
INSERT INTO text_analysis (article_id, tsvec)
96
- SELECT id, to_tsvector(text)
111
+ SELECT id, setweight( to_tsvector(name), 'A') || setweight(to_tsvector( text), 'D' )
97
112
FROM news_article
98
- WHERE id= " + articleId + @"
113
+ WHERE url=' " + article . URL + @"'
99
114
;" ) ;
100
115
}
101
116
}
@@ -121,13 +136,61 @@ public static List<NewsArticle> GetFilteredList(ListRequest request)
121
136
{
122
137
var q = db . From < NewsArticle > ( ) ;
123
138
q = q . Where ( art => request . LeftBoundDate <= art . Date && art . Date <= request . RightBoundDate ) ;
124
- q = q . Where ( art => art . URL . Contains ( request . Url ) ) ;
125
- //q = q.Where(request.Keywords);
126
- //q = q.Where(request.Entitities);
127
- q = request . OldestFirst ? q . OrderBy ( art => art . Date ) : q . OrderByDescending ( art => art . Date ) ;
139
+ q = q . Where ( art => art . URL . StartsWith ( request . Url ) ) ;
140
+
141
+ string keywords = request . Keywords ;
142
+ if ( ! keywords . IsNullOrEmpty ( ) )
143
+ {
144
+ keywords = keywords . Replace ( "\' " , "\' \' " ) ;
145
+ var results = db . Select < ( int ArtId , float Rank ) > ( @"
146
+ WITH query_rank AS (
147
+ SELECT article_id AS art_id, ts_rank(tsvec, websearch_to_tsquery('" + keywords + @"')) AS ts_rank_value
148
+ FROM text_analysis
149
+ )
150
+
151
+ SELECT id, ts_rank_value
152
+ FROM query_rank
153
+
154
+ INNER JOIN news_article
155
+ ON query_rank.ts_rank_value > 0
156
+ AND query_rank.art_id = news_article.id
157
+
158
+ ORDER BY ts_rank_value DESC
159
+ ;" )
160
+ . Map ( tup =>
161
+ new SearchRankResult ( )
162
+ {
163
+ ArtId = tup . ArtId ,
164
+ Rank = tup . Rank ,
165
+ Query = keywords
166
+ } ) ;
167
+ db . CreateTableIfNotExists < SearchRankResult > ( ) ;
168
+ foreach ( SearchRankResult result in results )
169
+ {
170
+ if ( ! db . Exists < SearchRankResult > ( r => r . ArtId == result . ArtId && r . Query == result . Query ) )
171
+ {
172
+ db . Insert ( result ) ;
173
+ }
174
+ }
175
+ q = q . Join < NewsArticle , SearchRankResult > ( ( art , rnk ) => art . Id == rnk . ArtId && rnk . Query == keywords ) ;
176
+ q = q . OrderByDescending < NewsArticle , SearchRankResult > ( ( art , rnk ) => rnk . Rank ) ;
177
+ }
178
+ else
179
+ {
180
+ q = request . OldestFirst ? q . OrderBy ( art => art . Date ) : q . OrderByDescending ( art => art . Date ) ;
181
+ }
182
+
183
+ if ( ! ( request . Entitities is null || request . Entitities . IsEmpty ( ) ) )
184
+ {
185
+ q = q . UnsafeWhere ( PgSql . Array ( request . Entitities ) + " <@ entities" ) ;
186
+ }
128
187
q = q . Limit ( request . Skip , request . Count ) ;
129
- q = q . Select ( art => new { art . URL , art . Name , art . Date } ) ;
188
+ q = q . Select ( art => new { art . Id , art . URL , art . Name , art . Date } ) ;
130
189
FilteredNews = db . Select ( q ) . ToList ( ) ;
190
+ if ( ! keywords . IsNullOrEmpty ( ) )
191
+ {
192
+ db . Delete < SearchRankResult > ( rnk => rnk . Query == keywords ) ;
193
+ }
131
194
}
132
195
return FilteredNews ;
133
196
}
0 commit comments