33using StackExchange . Redis ;
44using System ;
55using System . Collections . Generic ;
6+ using System . Threading . Tasks ;
67
78namespace NRediSearch
89{
@@ -81,6 +82,28 @@ public bool CreateIndex(Schema schema, IndexOptions options)
8182 return ( string ) _db . Execute ( "FT.CREATE" , args ) == "OK" ;
8283 }
8384
85+ /// <summary>
86+ /// Create the index definition in redis
87+ /// </summary>
88+ /// <param name="schema">a schema definition <seealso cref="Schema"/></param>
89+ /// <param name="options">index option flags <seealso cref="IndexOptions"/></param>
90+ /// <returns>true if successful</returns>
91+ public async Task < bool > CreateIndexAsync ( Schema schema , IndexOptions options )
92+ {
93+ var args = new List < object > ( ) ;
94+
95+ args . Add ( _boxedIndexName ) ;
96+ SerializeRedisArgs ( options , args ) ;
97+ args . Add ( "SCHEMA" . Literal ( ) ) ;
98+
99+ foreach ( var f in schema . Fields )
100+ {
101+ f . SerializeRedisArgs ( args ) ;
102+ }
103+
104+ return ( string ) await _db . ExecuteAsync ( "FT.CREATE" , args ) == "OK" ;
105+ }
106+
84107 /// <summary>
85108 /// Search the index
86109 /// </summary>
@@ -96,6 +119,21 @@ public SearchResult Search(Query q)
96119 return new SearchResult ( resp , ! q . NoContent , q . WithScores , q . WithPayloads ) ;
97120 }
98121
122+ /// <summary>
123+ /// Search the index
124+ /// </summary>
125+ /// <param name="q">a <see cref="Query"/> object with the query string and optional parameters</param>
126+ /// <returns>a <see cref="SearchResult"/> object with the results</returns>
127+ public async Task < SearchResult > SearchAsync ( Query q )
128+ {
129+ var args = new List < object > ( ) ;
130+ args . Add ( _boxedIndexName ) ;
131+ q . SerializeRedisArgs ( args ) ;
132+
133+ var resp = ( RedisResult [ ] ) await _db . ExecuteAsync ( "FT.SEARCH" , args ) ;
134+ return new SearchResult ( resp , ! q . NoContent , q . WithScores , q . WithPayloads ) ;
135+ }
136+
99137 /// <summary>
100138 /// Add a single document to the query
101139 /// </summary>
@@ -106,6 +144,27 @@ public SearchResult Search(Query q)
106144 /// <param name="replace">if set, and the document already exists, we reindex and update it</param>
107145 /// <param name="payload">if set, we can save a payload in the index to be retrieved or evaluated by scoring functions on the server</param>
108146 public bool AddDocument ( string docId , Dictionary < string , RedisValue > fields , double score = 1.0 , bool noSave = false , bool replace = false , byte [ ] payload = null )
147+ {
148+ var args = BuildAddDocumentArgs ( docId , fields , score , noSave , replace , payload ) ;
149+ return ( string ) _db . Execute ( "FT.ADD" , args ) == "OK" ;
150+ }
151+
152+ /// <summary>
153+ /// Add a single document to the query
154+ /// </summary>
155+ /// <param name="docId">the id of the document. It cannot belong to a document already in the index unless replace is set</param>
156+ /// <param name="score">the document's score, floating point number between 0 and 1</param>
157+ /// <param name="fields">a map of the document's fields</param>
158+ /// <param name="noSave">if set, we only index the document and do not save its contents. This allows fetching just doc ids</param>
159+ /// <param name="replace">if set, and the document already exists, we reindex and update it</param>
160+ /// <param name="payload">if set, we can save a payload in the index to be retrieved or evaluated by scoring functions on the server</param>
161+ public async Task < bool > AddDocumentAsync ( string docId , Dictionary < string , RedisValue > fields , double score = 1.0 , bool noSave = false , bool replace = false , byte [ ] payload = null )
162+ {
163+ var args = BuildAddDocumentArgs ( docId , fields , score , noSave , replace , payload ) ;
164+ return ( string ) await _db . ExecuteAsync ( "FT.ADD" , args ) == "OK" ;
165+ }
166+
167+ private List < object > BuildAddDocumentArgs ( string docId , Dictionary < string , RedisValue > fields , double score , bool noSave , bool replace , byte [ ] payload )
109168 {
110169 var args = new List < object > { _boxedIndexName , docId , score } ;
111170 if ( noSave )
@@ -129,8 +188,7 @@ public bool AddDocument(string docId, Dictionary<string, RedisValue> fields, dou
129188 args . Add ( ent . Key ) ;
130189 args . Add ( ent . Value ) ;
131190 }
132-
133- return ( string ) _db . Execute ( "FT.ADD" , args ) == "OK" ;
191+ return args ;
134192 }
135193
136194 /// <summary>
@@ -139,6 +197,12 @@ public bool AddDocument(string docId, Dictionary<string, RedisValue> fields, dou
139197 public bool ReplaceDocument ( string docId , Dictionary < string , RedisValue > fields , double score = 1.0 , byte [ ] payload = null )
140198 => AddDocument ( docId , fields , score , false , true , payload ) ;
141199
200+ /// <summary>
201+ /// replaceDocument is a convenience for calling addDocument with replace=true
202+ /// </summary>
203+ public Task < bool > ReplaceDocumentAsync ( string docId , Dictionary < string , RedisValue > fields , double score = 1.0 , byte [ ] payload = null )
204+ => AddDocumentAsync ( docId , fields , score , false , true , payload ) ;
205+
142206 /// <summary>
143207 /// Index a document already in redis as a HASH key.
144208 /// </summary>
@@ -149,14 +213,28 @@ public bool ReplaceDocument(string docId, Dictionary<string, RedisValue> fields,
149213 public bool AddHash ( string docId , double score , bool replace )
150214 {
151215 var args = new List < object > { _boxedIndexName , docId , score } ;
152-
153216 if ( replace )
154217 {
155218 args . Add ( "REPLACE" . Literal ( ) ) ;
156219 }
157-
158220 return ( string ) _db . Execute ( "FT.ADDHASH" , args ) == "OK" ;
159221 }
222+ /// <summary>
223+ /// Index a document already in redis as a HASH key.
224+ /// </summary>
225+ /// <param name="docId">the id of the document in redis. This must match an existing, unindexed HASH key</param>
226+ /// <param name="score">the document's index score, between 0 and 1</param>
227+ /// <param name="replace">if set, and the document already exists, we reindex and update it</param>
228+ /// <returns>true on success</returns>
229+ public async Task < bool > AddHashAsync ( string docId , double score , bool replace )
230+ {
231+ var args = new List < object > { _boxedIndexName , docId , score } ;
232+ if ( replace )
233+ {
234+ args . Add ( "REPLACE" . Literal ( ) ) ;
235+ }
236+ return ( string ) await _db . ExecuteAsync ( "FT.ADDHASH" , args ) == "OK" ;
237+ }
160238
161239 /// <summary>
162240 /// Get the index info, including memory consumption and other statistics.
@@ -165,8 +243,20 @@ public bool AddHash(string docId, double score, bool replace)
165243 /// <returns>a map of key/value pairs</returns>
166244 public Dictionary < string , RedisValue > GetInfo ( )
167245 {
168-
169- var res = ( RedisValue [ ] ) _db . Execute ( "FT.INFO" , _boxedIndexName ) ;
246+ return ParseGetInfo ( _db . Execute ( "FT.INFO" , _boxedIndexName ) ) ;
247+ }
248+ /// <summary>
249+ /// Get the index info, including memory consumption and other statistics.
250+ /// </summary>
251+ /// <remarks>TODO: Make a class for easier access to the index properties</remarks>
252+ /// <returns>a map of key/value pairs</returns>
253+ public async Task < Dictionary < string , RedisValue > > GetInfoAsync ( )
254+ {
255+ return ParseGetInfo ( await _db . ExecuteAsync ( "FT.INFO" , _boxedIndexName ) ) ;
256+ }
257+ static Dictionary < string , RedisValue > ParseGetInfo ( RedisResult value )
258+ {
259+ var res = ( RedisValue [ ] ) value ;
170260 var info = new Dictionary < string , RedisValue > ( ) ;
171261 for ( int i = 0 ; i < res . Length ; i += 2 )
172262 {
@@ -187,6 +277,16 @@ public bool DeleteDocument(string docId)
187277 return ( long ) _db . Execute ( "FT.DEL" , _boxedIndexName , docId ) == 1 ;
188278 }
189279
280+ /// <summary>
281+ /// Delete a document from the index.
282+ /// </summary>
283+ /// <param name="docId">the document's id</param>
284+ /// <returns>true if it has been deleted, false if it did not exist</returns>
285+ public async Task < bool > DeleteDocumentAsync ( string docId )
286+ {
287+ return ( long ) await _db . ExecuteAsync ( "FT.DEL" , _boxedIndexName , docId ) == 1 ;
288+ }
289+
190290 /// <summary>
191291 /// Drop the index and all associated keys, including documents
192292 /// </summary>
@@ -195,6 +295,14 @@ public bool DropIndex()
195295 {
196296 return ( string ) _db . Execute ( "FT.DROP" , _boxedIndexName ) == "OK" ;
197297 }
298+ /// <summary>
299+ /// Drop the index and all associated keys, including documents
300+ /// </summary>
301+ /// <returns>true on success</returns>
302+ public async Task < bool > DropIndexAsync ( )
303+ {
304+ return ( string ) await _db . ExecuteAsync ( "FT.DROP" , _boxedIndexName ) == "OK" ;
305+ }
198306
199307 /// <summary>
200308 /// Optimize memory consumption of the index by removing extra saved capacity. This does not affect speed
@@ -203,5 +311,13 @@ public long OptimizeIndex()
203311 {
204312 return ( long ) _db . Execute ( "FT.OPTIMIZE" , _boxedIndexName ) ;
205313 }
314+
315+ /// <summary>
316+ /// Optimize memory consumption of the index by removing extra saved capacity. This does not affect speed
317+ /// </summary>
318+ public async Task < long > OptimizeIndexAsync ( )
319+ {
320+ return ( long ) await _db . ExecuteAsync ( "FT.OPTIMIZE" , _boxedIndexName ) ;
321+ }
206322 }
207323}
0 commit comments