Neo4j可以在节点中存储字典吗?

时间:2014-04-17 11:42:02

标签: neo4j neo4jclient

我正在研究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 个答案:

答案 0 :(得分:5)

默认情况下,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());

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