-
Notifications
You must be signed in to change notification settings - Fork 74
/
SearchResponse.cs
158 lines (143 loc) · 5.32 KB
/
SearchResponse.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using System.Collections.Generic;
using System.Linq;
using Redis.OM;
namespace Redis.OM.Searching
{
/// <summary>
/// The result from a search.
/// </summary>
public class SearchResponse
{
/// <summary>
/// Initializes a new instance of the <see cref="SearchResponse"/> class.
/// </summary>
/// <param name="val">The redis response.</param>
public SearchResponse(RedisReply val)
{
var vals = val.ToArray();
DocumentCount = vals[0];
Documents = new Dictionary<string, IDictionary<string, string>>();
for (var i = 1; i < vals.Count(); i += 2)
{
var docId = (string)vals[i];
var documentHash = new Dictionary<string, string>();
var docArray = vals[i + 1].ToArray();
for (var j = 0; j < docArray.Length; j += 2)
{
documentHash.Add(docArray[j], docArray[j + 1]);
}
Documents.Add(docId, documentHash);
}
}
/// <summary>
/// Gets the number of documents found by the search.
/// </summary>
public long DocumentCount { get; }
/// <summary>
/// Gets the documents from the search.
/// </summary>
public IDictionary<string, IDictionary<string, string>> Documents { get; }
/// <summary>
/// gets document as a collection of the provided type.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <returns>A dictionary of the response type with their keys.</returns>
public IDictionary<string, T> DocumentsAs<T>()
where T : notnull
{
var dict = new Dictionary<string, T>();
foreach (var kvp in Documents)
{
var obj = RedisObjectHandler.FromHashSet<T>(kvp.Value);
dict.Add(kvp.Key, obj);
}
return dict;
}
}
/// <summary>
/// A strongly typed search response.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
#pragma warning disable SA1402
public class SearchResponse<T>
#pragma warning restore SA1402
where T : notnull
{
/// <summary>
/// Initializes a new instance of the <see cref="SearchResponse{T}"/> class.
/// </summary>
/// <param name="val">The response to use to initialize the Search Response.</param>
public SearchResponse(RedisReply val)
{
var type = typeof(T);
var underlyingType = Nullable.GetUnderlyingType(type);
if (type.IsPrimitive || type == typeof(string))
{
var @this = PrimitiveSearchResponse(val);
Documents = @this.Documents;
DocumentCount = @this.DocumentCount;
}
else if (underlyingType is { IsPrimitive: true })
{
var @this = PrimitiveSearchResponse(val);
Documents = @this.Documents;
DocumentCount = @this.DocumentCount;
}
else
{
var vals = val.ToArray();
DocumentCount = vals[0];
Documents = new Dictionary<string, T>();
for (var i = 1; i < vals.Count(); i += 2)
{
var docId = (string)vals[i];
var documentHash = new Dictionary<string, string>();
var docArray = vals[i + 1].ToArray();
for (var j = 0; j < docArray.Length; j += 2)
{
documentHash.Add(docArray[j], docArray[j + 1]);
}
var obj = RedisObjectHandler.FromHashSet<T>(documentHash);
Documents.Add(docId, obj);
}
}
}
private SearchResponse()
{
DocumentCount = 0;
Documents = new Dictionary<string, T>();
}
/// <summary>
/// Gets or sets the number of documents found by the search.
/// </summary>
public long DocumentCount { get; set; }
/// <summary>
/// Gets the documents.
/// </summary>
public IDictionary<string, T> Documents { get; }
/// <summary>
/// Gets a particular document by it's ID.
/// </summary>
/// <param name="key">the key to use to look up.</param>
public T this[string key] => Documents[key];
/// <summary>
/// Gets a particular element by its index in the collection.
/// </summary>
/// <param name="index">the index.</param>
internal T this[int index] => Documents.Values.ElementAt(index);
private static SearchResponse<T> PrimitiveSearchResponse(RedisReply redisReply)
{
var arr = redisReply.ToArray();
var response = new SearchResponse<T>();
response.DocumentCount = arr[0];
for (var i = 1; i < arr.Count(); i += 2)
{
var docId = (string)arr[i];
T? primitive = arr[i + 1].ToArray().Length > 1 ? (T)Convert.ChangeType(arr[i + 1].ToArray()[1], typeof(T)) : default;
response.Documents.Add(docId, primitive!);
}
return response;
}
}
}