Neo4j能否在节点中存储字典?

5

我正在使用C#并且使用neo4jclient。 我知道如果我向neo4jclient传递一个类对象,它可以创建一个节点(我已经尝试过了)。 现在在我的类中,我想添加一个字典属性,但是这样做不起作用。 我的代码:

 GraphClient client = getConnection();
 client.Cypher
       .Merge("(user:User { uniqueIdInItsApp: {id} , appId: {appId} })")
       .OnCreate()
       .Set("user = {newUser}")
       .WithParams(new
       {
           id = user.uniqueIdInItsApp,
           appId = user.appId,
           newUser = user
       })
       .ExecuteWithoutResults();

User 在 C# 中包含一个属性,它是一个 Dictionary。当执行cypher时,会显示错误。

MatchError: Map() (of class scala.collection.convert.Wrappers$JMapWrapper)

有没有人能帮助我?

1个回答

6

默认情况下,Neo4j不处理字典(Java中的Maps),所以你唯一的解决方案是使用自定义序列化器,将字典序列化为字符串属性...

以下代码仅适用于给定的类型,您需要做类似的事情,以便尽可能使用默认处理,并仅对您的类型使用此转换器:

//This is what I'm serializing
public class ThingWithDictionary
{
    public int Id { get; set; }
    public IDictionary<int, string> IntString { get; set; }
}

//This is the converter
public class ThingWithDictionaryJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var twd = value as ThingWithDictionary;
        if (twd == null)
            return;

        JToken t = JToken.FromObject(value);
        if (t.Type != JTokenType.Object)
        {
            t.WriteTo(writer);
        }
        else
        {
            var o = (JObject)t;
            //Store original token in a temporary var
            var intString = o.Property("IntString");
            //Remove original from the JObject
            o.Remove("IntString");
            //Add a new 'InsString' property 'stringified'
            o.Add("IntString", intString.Value.ToString());
            //Write away!
            o.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (objectType != typeof(ThingWithDictionary))
            return null;

        //Load our object
        JObject jObject = JObject.Load(reader);
        //Get the InsString token into a temp var
        var intStringToken = jObject.Property("IntString").Value;
        //Remove it so it's not deserialized by Json.NET
        jObject.Remove("IntString");

        //Get the dictionary ourselves and deserialize
        var dictionary = JsonConvert.DeserializeObject<Dictionary<int, string>>(intStringToken.ToString());

        //The output
        var output = new ThingWithDictionary();
        //Deserialize all the normal properties
        serializer.Populate(jObject.CreateReader(), output);

        //Add our dictionary
        output.IntString = dictionary;

        //return
        return output;
    }

    public override bool CanConvert(Type objectType)
    {
        //Only can convert if it's of the right type
        return objectType == typeof(ThingWithDictionary);
    }
}

然后在Neo4jClient中使用:
var client = new GraphClient(new Uri("http://localhost:7474/db/data/"));
client.Connect();
client.JsonConverters.Add( new ThingWithDictionaryJsonConverter());

当可用时,它将使用该转换器。


谢谢,Chris~ 我也使用类似的方法来解决它。 - user2234995
嗨,Chris,谢谢你的回答。我遇到了一个问题,每次运行带有graphClient的查询时,传递给ReadJson的序列化器参数都为null...这是代码片段,如果你有任何见解,我会很感激...此时我正在查看GitHub上的Neo4jClient源代码:GraphClient.Cypher .Create($"(e:Person {entity})") .WithParam("entity", node) .Return(e=>e.As<TNode>()).Result - Michel Triana
嗨@MichelTriana,我可能需要更多的信息 - 你能通过电子邮件/ Github / 新问题来提供吗?如果可以的话,我会尽力帮助! - Charlotte Skardon
@CharlotteSkardon 我和 @MichelTriana 一样遇到了同样的问题,即序列化对象为空,在 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 有人知道为什么吗?我知道这是很久以前的事情了。 - flieks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接