【问题标题】:Can Neo4j store a dictionary in a node?Neo4j 可以在节点中存储字典吗?
【发布时间】:2014-04-17 11:42:02
【问题描述】:

我正在使用 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。 执行密码时显示错误

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

谁能帮帮我?

【问题讨论】:

    标签: neo4j neo4jclient


    【解决方案1】:

    默认情况下,Neo4j 不处理字典(Java 中的地图),因此您唯一真正的解决方案是使用自定义序列化程序并将字典序列化为字符串属性...

    下面的代码只适用于给定的类型,你会想要做一些类似的事情,这样你就可以尽可能使用默认处理,并且只对你的类型使用这个转换器:

    //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());
    

    它会在可能的情况下使用该转换器。

    【讨论】:

    • 谢谢,克里斯~我也用类似的方法来解决它
    • 嗨,克里斯,感谢您的回答。我遇到了一个问题,每次我使用 graphClient 运行查询时,传递给 ReadJson 的序列化程序参数为空...这是代码 sn-p,如果您有任何见解,我将不胜感激...此时我我正在查看 GitHub 上的 Neo4jClient 源代码:GraphClient.Cypher .Create($"(e:Person {entity})") .WithParam("entity", node) .Return(e=>e.As( )).结果
    • 嗨@MichelTriana 我可能需要更多的工作 - 你能发电子邮件/github/新问题吗?如果可以的话我会帮忙的!