-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
125 lines (100 loc) · 3.85 KB
/
Program.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
using System.Net.Http.Json;
using Common.AiDevsApi.Contracts;
using Common.AiDevsApi.Models;
using Neo4j.Driver;
using S03E05;
using S03E05.Models;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddS03E05();
var host = builder.Build();
await using var scope = host.Services.CreateAsyncScope();
var sp = scope.ServiceProvider;
var neo4jDriver = sp.GetRequiredService<IDriver>();
const string GraphDbName = "neo4j";
var dbUsers = await ListUsers();
await LoadUsersToGraphDb(dbUsers);
Console.WriteLine("Users loaded");
var dbConnections = await ListConnections();
await LoadConnectionsToGraphDb(dbConnections);
Console.WriteLine("Connections loaded");
const string startName = "Rafał";
const string endName = "Barbara";
const string ShortestPathCypher =
"""
MATCH p = SHORTEST 1 (r:User {username: $startName})-[:KNOWS]-+(b:User {username: $endName})
RETURN [n IN nodes(p) | n.username] AS names
""";
var shortestPathResult = await neo4jDriver
.ExecutableQuery(ShortestPathCypher)
.WithParameters(new { startName, endName })
.ExecuteAsync();
var shortestPath = shortestPathResult
.Result
.Select(r => r["names"].As<List<object>>().Select(s => s.ToString()))
.Single();
Console.WriteLine(JsonSerializer.Serialize(shortestPath));
var aiDevsApiService = sp.GetRequiredService<IAiDevsApiService>();
var taskResponse = new TaskAnswer<object>()
{
Task = "connections",
Answer = string.Join(", ", shortestPath)
};
var taskResponseResult = await aiDevsApiService.VerifyTaskAnswerAsync(taskResponse);
Console.WriteLine(JsonSerializer.Serialize(taskResponseResult));
async Task LoadUsersToGraphDb(IEnumerable<DbUser> dbUsers)
{
await using var session = neo4jDriver.AsyncSession(o => o.WithDatabase(GraphDbName));
const string Cypher = "MERGE (u:User {id: $id, username: $username})";
foreach (var dbUser in dbUsers)
{
var result = await session.ExecuteWriteAsync(x => x.RunAsync(
Cypher,
new { id = dbUser.Id, username = dbUser.Username }));
}
}
async Task LoadConnectionsToGraphDb(IEnumerable<DbConnection> connections)
{
await using var session = neo4jDriver.AsyncSession(o => o.WithDatabase(GraphDbName));
const string Cypher = """
MATCH (u1:User {id: $user1Id})
MATCH (u2:User {id: $user2Id})
MERGE (u1)-[r:KNOWS]->(u2)
""";
foreach (var connection in connections)
{
var result = await session.ExecuteWriteAsync(x => x.RunAsync(
Cypher,
new { user1Id = connection.User1Id, user2Id = connection.User2Id }));
}
}
async Task<IReadOnlyList<DbUser>> ListUsers()
{
const string Command = "SELECT * FROM users";
var dbResponse = await RunDbCommand(Command);
var parsedResponse = JsonSerializer.Deserialize<DbResponse<DbUser>>(dbResponse)
?? throw new InvalidOperationException("Invalid API response");
return parsedResponse.Reply;
}
async Task<IReadOnlyList<DbConnection>> ListConnections()
{
const string Command = "SELECT * FROM connections";
var dbResponse = await RunDbCommand(Command);
var parsedResponse = JsonSerializer.Deserialize<DbResponse<DbConnection>>(dbResponse)
?? throw new InvalidOperationException("Invalid API response");
return parsedResponse.Reply;
}
async Task<string> RunDbCommand(string command)
{
var aiDevsOptions = sp.GetRequiredService<IOptions<AiDevsApiOptions>>().Value;
var taskOptions = sp.GetRequiredService<IOptions<S03E05Options>>().Value;
var dbRequest = new DatabaseRequest
{
ApiKey = aiDevsOptions.ApiKey,
Query = command,
};
var httpClient = sp.GetRequiredService<IHttpClientFactory>().CreateClient();
var response = await httpClient.PostAsJsonAsync(taskOptions.DatabaseApiUrl, dbRequest);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}