4

I've this model in my java class

@Document
public class Template {

    private String type;

    private String code;

    @Version
    Long version;
}

I need to add a new field, named template, and map this field as dynamic in other words I would model a document like this

{
  _id: 'id' 
  type:'myType',
  code:'myCode'
  template:{
    someFiled:[
      {
        subField1:'value1',
        subField2:'value2'
      },
      {
        sub1Field1:'1value1',
        sub1Field2:'1value2'
      }
      .......................
    ],
    otherField:[
      {
        otherField1:'value1',
        otherField2:'value2'
      }
    ],
    .........
  },
  version:1000L
}

There is any way to annotated a field as dynamic?

SOLUTION

    @Document
    public class Template {

        private String type;

        private String code;

        private Map<String, Object> template;

        @Version
        Long version;
    }
4
  • When you say "dynamic", what do you mean exactly: "the schema is not known in advance" or "it has nested structures in it" or a mix of both or something else? Commented May 5, 2016 at 2:59
  • @MarcTarin I don't know the schema in advance but essentially it is a nested structure Commented May 5, 2016 at 7:25
  • How about adding a JsonObject as a field, u will able to add any document in it then. Commented May 5, 2016 at 11:03
  • 1
    Undefined schemas have already been addressed here, here, here... your nested structure looks like a Map<String, List<Map<String, String>>>, but I'd use a BasicDBObject. Commented May 5, 2016 at 14:15

1 Answer 1

6

I found out a perfect solution. take my project for example:

@Data
@Document(collection = "logs")
public class Log {
    @Id
    private String id;
    private Object data;

    // data field can be a string
    public void setData(String str) {
        data = str;
    }
    // data field can be a {}
    public void setData(JsonObject jsonObject) {
        data = new BasicDBObject(jsonObject.getMap());
    }
    // data can be a []
    public void setData(JsonArray jsonArray) {
        BasicDBList list = new BasicDBList();
        list.addAll(jsonArray.getList());
        data = list;
    }
}

declare the data field as type of Object, implement 3 kind of setter for it.

Here are the test case:

@RunWith(SpringRunner.class)
@SpringBootTest
public class LogRepositoryTest {

    @Autowired
    private LogRepository logRepository;

    @Test
    public void test() {
        Log strLog = new Log();
        strLog.setData("string here");
        logRepository.save(strLog);
        Log objLog = new Log();
        objLog.setData(new JsonObject().put("key", "value").put("obj", new JsonObject()));
        logRepository.save(objLog);
        Log aryLog = new Log();
        aryLog.setData(new JsonArray().add("a").add("b").add("c"));
        logRepository.save(aryLog);
    }
}

And the result:

{
        "_id" : ObjectId("5a09fa46a15b065268a0a157"),
        "_class" : "ltd.linkcon.spider.domain.Log",
        "data" : "string here"
}
{
        "_id" : ObjectId("5a09fa46a15b065268a0a158"),
        "_class" : "ltd.linkcon.spider.domain.Log",
        "data" : {
                "key" : "value",
                "obj" : [ ]
        }
}
{
        "_id" : ObjectId("5a09fa46a15b065268a0a159"),
        "_class" : "ltd.linkcon.spider.domain.Log",
        "data" : [
                "a",
                "b",
                "c"
        ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

This solution can also avoid spring to add _class and map field while mapping.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.