Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define Mongo Schema Validation using Spring

I want to define a Collection in Mongo using Spring-boot with a JSON Schema validator option (https://docs.mongodb.com/manual/core/schema-validation/#json-schema), I don't want a JSR-303 Bean validation (this is not a valid answer Spring data mongoDb not null annotation like Spring data Jpa), but define, at the moment of the creation of the Collection, an option that is showed in the JSON using CollectionInfos().

Example, if I define an Account model class likes:

public class Account {

@Id
private String id;

private String name;

private String surname;

@NotNull
private String username;
}

I want that the collection has, using db.getCollectionInfos(), a json likes:

[
{
    "name" : "account",
    "type" : "collection",
    "options" : {
        "validator" : {
            "$jsonSchema" : {
                "bsonType" : "object",
                "required" : [ 
                    "username"
                ]
            }
        }
    },
    "info" : {
        "readOnly" : false,
        "uuid" : UUID("979cdc4b-d6f3-4aef-bc89-3eee812773a5")
    },
    "idIndex" : {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "databaseName.account"
    }
}
]

The procedure could be similar to spring.jpa.hibernate.ddl-auto = create, because it defines rules at the schema level, and not similar to Bean validator, that defines rules at the Application level.

like image 804
Federico Gatti Avatar asked May 04 '18 07:05

Federico Gatti


People also ask

Does MongoDB support schema validation?

MongoDB uses a flexible schema model, which means that documents in a collection do not need to have the same fields or data types by default. Once you've established an application schema, you can use schema validation to ensure there are no unintended schema changes or improper data types.

How do I add a validation rule in MongoDB?

If you want to "add a validation rule" then there are methods which depend on the current state of the collection. In either case, there actually is no "add to" function, but the action instead is to "replace" all the validation rules with new ones to specify. Read on for the rules of how this works.

How do you validate a JSON Schema?

The simplest way to check if JSON is valid is to load the JSON into a JObject or JArray and then use the IsValid(JToken, JsonSchema) method with the JSON Schema. To get validation error messages, use the IsValid(JToken, JsonSchema, IList<String> ) or Validate(JToken, JsonSchema, ValidationEventHandler) overloads.


1 Answers

JsonSchema is supported by Spring Data MongoDB as of version 2.1. Please see the Reference Documentation for details. You can use a builder like below to define your schema.

MongoJsonSchema schema = MongoJsonSchema.builder()
    .required("username")
    .properties(JsonSchemaProperty.string("username"))
    .build();

template.createCollection("account", CollectionOptions.empty().schema(schema));

At the time of writing json schema creation from a domain type is not support. However you may want to join the discussion DATAMONGO-1849 and/or give the snapshots of PR#733 a try.

The suggestion would turn the DomainType into a MongoJsonSchema by calling something like MongoJsonSchema schema = schemaCreator.createSchemaFor(DomainType.class);

public class DomainType {

    private final String requiredCtorArg;
    private final @Nullable String nullableCtorArg;
    private String optionalArg;

    public DomainType(String requiredCtorArg, @Nullable String nullableCtorArg) {

        this.requiredCtorArg = requiredCtorArg;
        this.nullableCtorArg = nullableCtorArg;
    }

    // gettter / setter omitted 
}
{
    'type' : 'object',
    'required' : ['requiredCtorArg'],
    'properties' : {
        'requiredCtorArg' : { 'type' : 'string' },
        'nullableCtorArg' : { 'type' : 'string' },
        'optionalArg' : { 'type' : 'string' }
     }
}
like image 121
Christoph Strobl Avatar answered Oct 05 '22 10:10

Christoph Strobl