Announcement Announcement Module
Collapse
No announcement yet.
Spring Data Neo4j: How to map java.util.Map<String,String> field? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Data Neo4j: How to map java.util.Map<String,String> field?

    Hello,

    I have an relationship node class like this :

    @RelationshipNode
    public class MyConnection {
    private String title;
    private long duration;
    private Map<String,String> attributes;
    ...
    }

    When using Spring data Neo4J mapping layer, it naturally creates relationship nodes in Neo4j with keys "title" and "duration" corresponding to names of my class fields, but Map<String,String> field is not persisted. I would like those key-value entries in this Map to be also persisted inside this relationship node also as list of properties, but I understand the problem that I would have to distinguish this map field from other fields.

    I could decide for eg. to add additional prefix, something like "fieldName_" + entry.getKey() for name of property.
    Is it possible somehow to add some loading/saving interceptor in Spring-Data-Neo4j lib so it can work when loading/persisting this class insatnces, or it's not possible so I would have to use low-level Neo4 API for that (Neo4JTemplate)? I don't like later because I don't know how elegant it would be to mix those two approaches in my application.

    Regards,
    Vjeran

  • #2
    You would use the DynamicProperties instead of the Map which is then mapped to node-attributes.

    See this test, on how to use it.

    Code:
    @NodeEntity
    public class Person {
        @GraphId
    	private Long graphId;
    
    	private DynamicProperties personalProperties;
    	public void setProperty(String key, Object value) {
    		personalProperties.setProperty(key, value);
    	}
    
    	public Object getProperty(String key) {
    		return personalProperties.getProperty(key);
    	}
    }
    @Test
        public void testCreateOutsideTransaction() {
            Person p = new Person("James", 35);
            p.setProperty("s", "String");
            p.setProperty("x", 100);
            p.setProperty("pi", 3.1415);
            persist(p);
            assertEquals(3, IteratorUtil.count(p.getPersonalProperties().getPropertyKeys()));
            assertProperties(nodeFor(p));
            p.setProperty("s", "String two");
            persist(p);
            assertEquals("String two", nodeFor(p).getProperty("personalProperties-s"));
        }

    Comment


    • #3
      Oh, great!
      Thanx.

      Comment


      • #4
        I noticed a shortcoming with current way of persisting DynamicProperties - this map entries are stored with property names constructed with prefix (derived from DynamicProperties field name) and map key, separated by dash ("-"), and since dash is a special character inside Cypher, it is not simply possible to query these node properties by using query piece such as:

        Code:
        node.prefix-mapkey
        , but one has to use quite unknown "backtick" character for quoting node property name, such as:
        Code:
        node.`prefix-mapkey`
        Therefore, I would suggest that separation character is underscore, which is not treated as special character as I know.

        Regards,
        Vjeran

        Comment


        • #5
          Good point,

          can you raise an JIRA issue? for that

          Better to make it configurable

          Michael

          Comment

          Working...
          X