更新图数据库相关数据
This commit is contained in:
339
Ramitta/Neo4jService.cs
Normal file
339
Ramitta/Neo4jService.cs
Normal file
@@ -0,0 +1,339 @@
|
||||
using Neo4j.Driver;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ramitta
|
||||
{
|
||||
public class Neo4jService
|
||||
{
|
||||
private IDriver _driver;
|
||||
|
||||
public Neo4jService(string uri, string user, string password)
|
||||
{
|
||||
_driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_driver?.Dispose();
|
||||
}
|
||||
|
||||
// 创建任意节点,支持更多属性
|
||||
public async Task CreateNodeAsync(string nodeType, Dictionary<string, object> properties)
|
||||
{
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
// 动态生成属性字符串
|
||||
var propertyString = string.Join(", ", properties.Keys);
|
||||
var values = new Dictionary<string, object>();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
values.Add(prop.Key, prop.Value);
|
||||
}
|
||||
|
||||
var query = $"CREATE (n:{nodeType} {{{string.Join(", ", properties.Keys.Select(k => $"{k}: ${k}"))}}})";
|
||||
await session.RunAsync(query, values);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Dictionary<string, string>>> GetRelatedNodesAsync(
|
||||
string nodeLabel,
|
||||
Dictionary<string, string> nodeProperties)
|
||||
{
|
||||
// 构建属性条件字符串
|
||||
var propertyConditions = new List<string>();
|
||||
foreach (var prop in nodeProperties)
|
||||
{
|
||||
propertyConditions.Add($"{prop.Key}: '{prop.Value.Replace("'", "\\'")}'");
|
||||
}
|
||||
|
||||
var propertiesString = string.Join(", ", propertyConditions);
|
||||
|
||||
var query = $@"
|
||||
MATCH (h:{nodeLabel} {{{propertiesString}}})-[r]-(related)
|
||||
RETURN DISTINCT h";
|
||||
|
||||
var resultList = new List<Dictionary<string, string>>();
|
||||
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
var result = await session.RunAsync(query);
|
||||
|
||||
await result.ForEachAsync(record =>
|
||||
{
|
||||
var hNode = record["h"].As<INode>();
|
||||
resultList.Add(ConvertNodeToDictionary(hNode));
|
||||
});
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> ConvertNodeToDictionary(INode node)
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
|
||||
// 添加所有属性
|
||||
foreach (var property in node.Properties)
|
||||
{
|
||||
dict[property.Key] = property.Value?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 创建或合并节点
|
||||
public async Task MergeNodeAsync(string nodeType, Dictionary<string, object> properties)
|
||||
{
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
// 动态生成属性字符串
|
||||
var propertyString = string.Join(", ", properties.Keys);
|
||||
var values = new Dictionary<string, object>();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
values.Add(prop.Key, prop.Value);
|
||||
}
|
||||
|
||||
var query = $"MERGE (n:{nodeType} {{{string.Join(", ", properties.Keys.Select(k => $"{k}: ${k}"))}}})";
|
||||
await session.RunAsync(query, values);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<Dictionary<string, object>>> GetNodesAsync(string nodeType = null)
|
||||
{
|
||||
var result = new List<Dictionary<string, object>>();
|
||||
|
||||
var query = nodeType == null
|
||||
? "MATCH (n) RETURN n"
|
||||
: $"MATCH (n:{nodeType}) RETURN n";
|
||||
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
var cursor = await session.RunAsync(query);
|
||||
|
||||
while (await cursor.FetchAsync())
|
||||
{
|
||||
var node = cursor.Current["n"].As<INode>();
|
||||
var nodeProperties = new Dictionary<string, object>(node.Properties);
|
||||
|
||||
// 添加节点ID和标签信息
|
||||
nodeProperties["_id"] = node.Id;
|
||||
nodeProperties["_labels"] = node.Labels.ToArray();
|
||||
|
||||
result.Add(nodeProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// 创建任意关系,支持动态定义关系类型
|
||||
public enum ArrowDirection
|
||||
{
|
||||
Left, // 反向关系
|
||||
Right, // 正向关系(默认)
|
||||
Both // 双向关系
|
||||
}
|
||||
public async Task CreateRelationshipAsync(
|
||||
string relationshipType,
|
||||
string nodeType1, string nodeTap1, string nodeName1,
|
||||
string nodeType2, string nodeTap2, string nodeName2,
|
||||
ArrowDirection arrow = ArrowDirection.Right
|
||||
)
|
||||
{
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
var query = $"MATCH (a:{nodeType1} {{{nodeTap1}: $name1}}), (b:{nodeType2} {{{nodeTap2}: $name2}}) ";
|
||||
|
||||
if (arrow == ArrowDirection.Right)
|
||||
query+=$"MERGE (a)-[:{relationshipType}]->(b)";
|
||||
else if (arrow == ArrowDirection.Left)
|
||||
query += $"MERGE (b)-[:{relationshipType}]->(a)";
|
||||
else if (arrow == ArrowDirection.Both) {
|
||||
query += $"MERGE (a)-[:{relationshipType}]->(b)";
|
||||
query += $"MERGE (b)-[:{relationshipType}]->(a)";
|
||||
}
|
||||
await session.RunAsync(query, new { name1 = nodeName1, name2 = nodeName2 });
|
||||
}
|
||||
}
|
||||
public async Task<List<Dictionary<string, object>>> GetRelatedNodesAsync(
|
||||
string nodeName,
|
||||
string nodeType, // 默认值为 "Person"
|
||||
string relationshipType = null,
|
||||
Dictionary<string, object> additionalNodeFilters = null, // 可选的节点属性过滤
|
||||
Dictionary<string, object> additionalRelationshipFilters = null // 可选的关系属性过滤
|
||||
)
|
||||
{
|
||||
var result = new List<Dictionary<string, object>>();
|
||||
|
||||
// 构建基本的查询部分
|
||||
var query = new StringBuilder($"MATCH (a:{nodeType} {{name: $name}})");
|
||||
|
||||
// 如果有额外的节点过滤条件,加入到查询中
|
||||
if (additionalNodeFilters != null && additionalNodeFilters.Count > 0)
|
||||
{
|
||||
foreach (var filter in additionalNodeFilters)
|
||||
{
|
||||
query.Append($" AND a.{filter.Key} = ${filter.Key}");
|
||||
}
|
||||
}
|
||||
|
||||
// 根据关系类型添加关系部分
|
||||
var relationshipFilter = relationshipType != null ? $":{relationshipType}" : "";
|
||||
query.Append($"-[r{relationshipFilter}]->(b)");
|
||||
|
||||
// 如果有关系的额外过滤条件,加入到查询中
|
||||
if (additionalRelationshipFilters != null && additionalRelationshipFilters.Count > 0)
|
||||
{
|
||||
foreach (var filter in additionalRelationshipFilters)
|
||||
{
|
||||
query.Append($" AND r.{filter.Key} = ${filter.Key}");
|
||||
}
|
||||
}
|
||||
|
||||
// 添加返回部分
|
||||
query.Append(" RETURN b");
|
||||
|
||||
// 合并所有的参数
|
||||
var parameters = new Dictionary<string, object> { { "name", nodeName } };
|
||||
|
||||
// 如果有节点过滤条件,合并到参数中
|
||||
if (additionalNodeFilters != null)
|
||||
{
|
||||
foreach (var filter in additionalNodeFilters)
|
||||
{
|
||||
parameters[filter.Key] = filter.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有关系过滤条件,合并到参数中
|
||||
if (additionalRelationshipFilters != null)
|
||||
{
|
||||
foreach (var filter in additionalRelationshipFilters)
|
||||
{
|
||||
parameters[filter.Key] = filter.Value;
|
||||
}
|
||||
}
|
||||
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
var cursor = await session.RunAsync(query.ToString(), parameters);
|
||||
|
||||
// 遍历查询结果
|
||||
while (await cursor.FetchAsync())
|
||||
{
|
||||
var relatedNode = cursor.Current["b"].As<INode>(); // 获取目标节点对象
|
||||
|
||||
// 将节点的所有属性加入结果
|
||||
var nodeProperties = new Dictionary<string, object>();
|
||||
foreach (var property in relatedNode.Properties)
|
||||
{
|
||||
nodeProperties[property.Key] = property.Value;
|
||||
}
|
||||
result.Add(nodeProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Dictionary<string, object>>> GetRelationshipsAsync(
|
||||
string nodeName,
|
||||
string nodeType = null,
|
||||
string relationshipType = null,
|
||||
bool includeIncoming = false,
|
||||
bool includeOutgoing = true)
|
||||
{
|
||||
var result = new List<Dictionary<string, object>>();
|
||||
var relationshipQuery = "";
|
||||
|
||||
// 根据关系方向构建查询
|
||||
if (relationshipType != null)
|
||||
{
|
||||
if (includeOutgoing && includeIncoming)
|
||||
{
|
||||
relationshipQuery = $"-[:{relationshipType}]-";
|
||||
}
|
||||
else if (includeOutgoing)
|
||||
{
|
||||
relationshipQuery = $"-[:{relationshipType}]->";
|
||||
}
|
||||
else if (includeIncoming)
|
||||
{
|
||||
relationshipQuery = $"<-[:{relationshipType}]-";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (includeOutgoing && includeIncoming)
|
||||
{
|
||||
relationshipQuery = "-[]-";
|
||||
}
|
||||
else if (includeOutgoing)
|
||||
{
|
||||
relationshipQuery = "-[]->";
|
||||
}
|
||||
else if (includeIncoming)
|
||||
{
|
||||
relationshipQuery = "<-[]-";
|
||||
}
|
||||
}
|
||||
|
||||
// 构造MATCH查询
|
||||
var query = $"MATCH (a:{nodeType ?? "Person"} {{name: $name}}){relationshipQuery}(b) RETURN b";
|
||||
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
var cursor = await session.RunAsync(query, new { name = nodeName });
|
||||
|
||||
// 遍历查询结果
|
||||
while (await cursor.FetchAsync())
|
||||
{
|
||||
var relatedNode = cursor.Current["b"].As<INode>(); // 获取目标节点对象
|
||||
|
||||
// 将节点的所有属性加入结果
|
||||
var nodeProperties = new Dictionary<string, object>();
|
||||
foreach (var property in relatedNode.Properties)
|
||||
{
|
||||
nodeProperties[property.Key] = property.Value;
|
||||
}
|
||||
result.Add(nodeProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// 删除特定节点和它的关系
|
||||
public async Task DeleteNodeAsync(string nodeType, string nodeName)
|
||||
{
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
await session.RunAsync($"MATCH (n:{nodeType} {{name: $name}}) DETACH DELETE n", new { name = nodeName });
|
||||
}
|
||||
}
|
||||
|
||||
// 删除所有节点和关系
|
||||
public async Task DeleteAllNodesAndRelationshipsAsync()
|
||||
{
|
||||
using (var session = _driver.AsyncSession())
|
||||
{
|
||||
await session.RunAsync("MATCH (n) DETACH DELETE n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user