-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRepository.cs
More file actions
233 lines (218 loc) · 8.38 KB
/
Copy pathRepository.cs
File metadata and controls
233 lines (218 loc) · 8.38 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using GraphStore.Models;
using Neo4j.Driver;
namespace GraphStore;
public interface IRepository
{
Task<IEnumerable<Item>> GetAllItemsForOrder(string orderId);
Task<OrderTotalPriceResult> GetTotalPrice(string orderId);
Task<IEnumerable<Order>> GetAllOrdersForCustomer(string customerId);
Task<IEnumerable<Item>> GetAllBoughtItemsForCustomer(string customerId);
Task<int> GetTotalItemsBoughtForCustomer(string customerId);
Task<decimal> GetTotalSpentAmount(string customerId);
Task<List<(int itemId, int totalBought)>> GetAllItemsPopularity();
Task<List<Item>> GetAllItemsViewedByCustomer(string customerId);
Task<List<Item>> GetAllBoughtAlongWith(string itemId);
Task<List<Customer>> GetAllCustomersWhoBoughtItem(string itemId);
Task<List<Item>> GetAllViewedAndNotBoughtItems(string customerId);
}
public class Repository : IRepository
{
private readonly IDriver _driver;
private readonly QueryConfig queryConfig;
public Repository(IDriver driver)
{
_driver = driver;
queryConfig = new QueryConfig(database: "GraphStore");
}
public async Task<IEnumerable<Item>> GetAllItemsForOrder(string orderId)
{
var queryResults = await _driver
.ExecutableQuery(
"MATCH (o:Order {id:$orderId})-[:CONTAINS]->(i:Item) " +
"RETURN i as item")
.WithParameters(new { orderId })
.WithConfig(queryConfig)
.ExecuteAsync();
var nodes = queryResults.Result.Select(record => record["item"].As<INode>());
var items = nodes.Select(node => GetItemFromNode(node)).ToList();
return items;
}
public async Task<OrderTotalPriceResult> GetTotalPrice(string orderId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (o:Order {id:$orderId})-[:CONTAINS]->(i:Item) " +
"RETURN o.id as orderId, sum(i.price) as totalPrice"
)
.WithParameters(new { orderId })
.WithConfig(queryConfig)
.ExecuteAsync();
var result = queryResult
.Select(record => new OrderTotalPriceResult
(
record["orderId"].As<string>(),
record["totalPrice"].As<decimal>()
))
.Single();
return result;
}
public async Task<IEnumerable<Order>> GetAllOrdersForCustomer(string customerId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (c:Customer {id:$customerId})-[:PLACED]->(o:Order) " +
"RETURN o as order")
.WithParameters(new { customerId })
.WithConfig(queryConfig)
.ExecuteAsync();
var orders = queryResult
.Select(record => record["order"].As<INode>())
.Select(node => new Order
{
Id = node.Properties["id"].As<string>(),
CustomerId = customerId
})
.ToList();
return orders;
}
public async Task<IEnumerable<Item>> GetAllBoughtItemsForCustomer(string customerId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (c:Customer {id:$customerId})-[:PLACED]->(o:Order)-[:CONTAINS]->(i:Item)" +
"RETURN i as item")
.WithParameters(new { customerId })
.WithConfig(queryConfig)
.ExecuteAsync();
var items = queryResult.Select(record => record["item"].As<INode>())
.Select(node => GetItemFromNode(node))
.ToList();
return items;
}
public async Task<int> GetTotalItemsBoughtForCustomer(string customerId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (c:Customer)-[:PLACED]->(o:Order)-[:CONTAINS]->(i:Item) " +
"WHERE c.id = $customerId " +
"RETURN count(i.price) AS totalItems"
)
.WithParameters(new { customerId })
.WithConfig(queryConfig)
.ExecuteAsync();
var totalItems = queryResult
.Select(record => record["totalItems"].As<int>())
.Single();
return totalItems;
}
public async Task<decimal> GetTotalSpentAmount(string customerId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (c:Customer)-[:PLACED]->(o:Order)-[:CONTAINS]->(i:Item) " +
"WHERE c.id = $customerId " +
"RETURN sum(i.price) AS totalAmountSpent "
)
.WithParameters(new { customerId })
.WithConfig(queryConfig)
.ExecuteAsync();
var totalSpentAmount = queryResult
.Select(record => record["totalAmountSpent"].As<decimal>())
.Single();
return totalSpentAmount;
}
public async Task<List<(int itemId, int totalBought)>> GetAllItemsPopularity()
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (i:Item)<-[r:CONTAINS]-(o:Order) " +
"RETURN i.id as itemId, count(i) AS totalBought " +
"ORDER BY totalBought DESC"
)
.WithConfig(queryConfig)
.ExecuteAsync();
var totalSpentAmount = queryResult
.Select(record => (
itemId: record["itemId"].As<int>(),
totalBought: record["totalBought"].As<int>())
)
.ToList();
return totalSpentAmount;
}
public async Task<List<Item>> GetAllItemsViewedByCustomer(string customerId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (c:Customer)-[:VIEWED]->(i:Item) " +
"WHERE c.id = $customerId " +
"RETURN i as item"
)
.WithParameters(new { customerId })
.WithConfig(queryConfig)
.ExecuteAsync();
var viewedItems = queryResult
.Select(record => record["item"].As<INode>())
.Select(node => GetItemFromNode(node))
.ToList();
return viewedItems;
}
public async Task<List<Item>> GetAllBoughtAlongWith(string itemId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (searchItem:Item {id:$itemId})<-[:CONTAINS]-(o:Order)-[:CONTAINS]->(i:Item) " +
"RETURN DISTINCT i as item"
)
.WithParameters(new { itemId })
.WithConfig(queryConfig)
.ExecuteAsync();
var boughtAlongWith = queryResult
.Select(record => record["item"].As<INode>())
.Select(node => GetItemFromNode(node))
.ToList();
return boughtAlongWith;
}
public async Task<List<Customer>> GetAllCustomersWhoBoughtItem(string itemId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (i:Item)-[r]-{2}(c:Customer) " +
"WHERE i.id = $itemId " +
"RETURN DISTINCT c as customer"
)
.WithParameters(new { itemId })
.WithConfig(queryConfig)
.ExecuteAsync();
var customers = queryResult
.Select(record => record["customer"].As<INode>())
.Select(node => new Customer { Id = node["id"].As<string>() })
.ToList();
return customers;
}
public async Task<List<Item>> GetAllViewedAndNotBoughtItems(string customerId)
{
var (queryResult, _) = await _driver
.ExecutableQuery(
"MATCH (c:Customer)-[v:VIEWED]->(i:Item) " +
"WHERE c.id = $customerId AND NOT EXISTS {" +
" MATCH (c)-[:PLACED]->(o)-[:CONTAINS]->(i)" +
"} " +
"RETURN i as item"
)
.WithParameters(new { customerId })
.WithConfig(queryConfig)
.ExecuteAsync();
var viewedItems = queryResult
.Select(record => record["item"].As<INode>())
.Select(node => GetItemFromNode(node))
.ToList();
return viewedItems;
}
private Item GetItemFromNode(INode node) => new Item
{
Id = node.Properties["id"].As<string>(),
Name = node.Properties["name"].As<string>(),
Price = node.Properties["price"].As<decimal>(),
Likes = node.Properties["likes"].As<int>(),
};
}