0

I am storing game states in a MongoDB database and am using Spring Data to manage my database interactions. I am new to Spring Data and am unsure how to deal with the following scenario.

I have a document of type "Game" with a bunch of properties such as id, timestamp, etc... One of these properties is a list of actions taken by users. These actions are of the form:

{ type: 2 }, {type: 3, value: 4}, {type: 5, id: 1234}, {type 6}, {type: 5, value: 6, id: 56}

In other words, an action can have three properties: type, value, and id. However, not every action requires all three values to be stored. I want to avoid having a bunch of null values in my database, and would like my database to just not include and id or a value if they are not specified.

Using Spring Data's MongoRepository model, I am not sure how to achieve this. I can create a CRUD Game class and have one of its properties be a list of Action (where Action itself is a CRUD class with properties type, value, and id), but won't that end up storing null values in the database if I do not specify the value or id?

In short, how can I use Spring Data's MongoRepository but still maintain the flexibility of being able to store lists of objects with varying parameters or object types in general.

1
  • Have you tried using a Map<String,Integer>. It can help you solve your problem Commented Jun 18, 2020 at 4:56

1 Answer 1

1

I will explain how varying fields are handled with an example. The following Game.java POJO class represents the object mapping to the game collection document.

public class Game {

    String name;
    List<Actions> actions;

    public Game(String name, List<Actions> actions) {
        this.name = name;
        this.actions = actions;
    }

    public String getName() {
        return name;
    }

    public List<Actions> getActions() {
        return actions;
    }

    // other get/set methods, override, etc..


    public static class Actions {

        Integer id;
        String type;

        public Actions() {
        }

        public Actions(Integer id) {
            this.id = id;
        }

        public Actions(Integer id, String type) {
            this.id = id;
            this.type = type;
        }

        public Integer getId() {
            return id;
        }

        public String getType() {
            return type;
        }

        // other methods
    }
}

For the Actions class you need to provide constructors with the possible combinations. Use the appropriate constructor with id, type, etc. For example, create a Game object and save to the database:

Game.Actions actions= new Game.Actions(new Integer(1000));
Game g1 = new Game("G-1", Arrays.asList(actions));
repo.save(g1);

This is stored in the database collection game as follows (queried from mongo shell):

{
        "_id" : ObjectId("5eeafe2043f875621d1e447b"),
        "name" : "G-1",
        "actions" : [
                {
                        "_id" : 1000
                }
        ],
        "_class" : "com.example.demo.Game"
}

Note the actions array. As we had stored only the id field in the Game.Actions object, only that field is stored. Even though you specify all the fields in the class, only those provided with values are persisted.

These are two more documents with Game.Actions created with type only and id + type using the appropriate constructors:

{
        "_id" : ObjectId("5eeb02fe5b86147de7dd7484"),
        "name" : "G-9",
        "actions" : [
                {
                        "type" : "type-x"
                }
        ],
        "_class" : "com.example.demo.Game"
}
{
        "_id" : ObjectId("5eeb034d70a4b6360d5398cc"),
        "name" : "G-11",
        "actions" : [
                {
                        "_id" : 2,
                        "type" : "type-y"
                }
        ],
        "_class" : "com.example.demo.Game"
}
Sign up to request clarification or add additional context in comments.

2 Comments

Is the static nature of the Action class important? Or could I just create a new non-static class called Action with those two constructors? Also, does this mean that properties with null values (i.e. properties that haven't been initialized) will not be included when saving to the db?
(1) You can create another class, Actions. Static nested class is associated with the enclosing (outer) class. (2) Fields with not assigned values and with default null values are not stored in the database (as the example shows). It is true with any Pojo class mapped to the collection document.

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.