From 365430ce446bd0390d1bac870c05bfc75b971541 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 11 Jan 2018 15:27:24 +0100 Subject: [PATCH] DATAMONGO-1835 - Documentation. Original pull request: #524. --- .../mongodb/core/schema/MongoJsonSchema.java | 31 ++++ src/main/asciidoc/new-features.adoc | 4 +- src/main/asciidoc/reference/mongo-3.adoc | 15 ++ src/main/asciidoc/reference/mongodb.adoc | 151 +++++++++++++++++- 4 files changed, 193 insertions(+), 8 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java index f65814850..f837c0bfb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java @@ -23,6 +23,37 @@ import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.Object import org.springframework.util.Assert; /** + * Interface defining MongoDB-specific JSON schema object. New objects can be built with {@link #builder()}, for + * example: + * + *
+ * MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname")
+ * 		.properties(string("firstname").possibleValues("luke", "han"),
+ * 				object("address").properties(string("postCode").minLength(4).maxLength(5))
+ *
+ * 		).build();
+ * 
+ * + * resulting in the following schema: + * + *
+ *  {
+  "type": "object",
+  "required": [ "firstname", "lastname" ],
+  "properties": {
+    "firstname": {
+      "type": "string", "enum": [ "luke", "han" ],
+    },
+    "address": {
+      "type": "object",
+      "properties": {
+        "postCode": { "type": "string", "minLength": 4, "maxLength": 5 }
+      }
+    }
+  }
+}
+ * 
+ * * @author Christoph Strobl * @since 2.1 **/ diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index ec3fbeaf2..526c23478 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,8 +5,8 @@ == What's new in Spring Data MongoDB 2.1 * Cursor-based aggregation execution. * <> for imperative and reactive Template API. -* `validator` support for collections. -* `$jsonSchema` support for queries. +* <>. +* <> for queries and collection creation. [[new-features.2-0-0]] == What's new in Spring Data MongoDB 2.0 diff --git a/src/main/asciidoc/reference/mongo-3.adoc b/src/main/asciidoc/reference/mongo-3.adoc index 3ab427b4d..281a63a60 100644 --- a/src/main/asciidoc/reference/mongo-3.adoc +++ b/src/main/asciidoc/reference/mongo-3.adoc @@ -81,6 +81,21 @@ In order to use authentication with XML configuration use the `credentials` attr ---- +[[mongo.mongo-3.validation]] +=== Server-side Validation + +MongoDB supports https://docs.mongodb.com/manual/core/schema-validation/[Schema Validation] as of version 3.2 with query operators +and as of version 3.6 JSON-schema based validation. + +This chapter will point out the specialties for validation in MongoDB and how to apply JSON schema validation. + +[[mongo.mongo-3.validation.json-schema]] +==== JSON Schema Validation + +MongoDB 3.6 allows validation and querying of documents using JSON schema draft 4 including core specification and validation specification, with some differences. `$jsonSchema` can be used in a document validator (when creating a collection), which enforces that inserted or updated documents are valid against the schema. It can also be used to query for documents with the `find` command or `$match` aggregation stage. + +Spring Data MongoDB supports MongoDB's specific JSON schema implementation to define and use schemas. See <> for further details. + [[mongo.mongo-3.misc]] === Other things to be aware of diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 9ee53cab9..38f757e13 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -1054,6 +1054,8 @@ As you can see most methods return the `Criteria` object to provide a fluent sty * `Criteria` *regex* `(String re)` Creates a criterion using a `$regex` * `Criteria` *size* `(int s)` Creates a criterion using the `$size` operator * `Criteria` *type* `(int t)` Creates a criterion using the `$type` operator +* `Criteria` *matchingDocumentStructure* `(MongoJsonSchema schema)` Creates a criterion using the `$jsonSchema` operator for <>. `$jsonSchema` can only be applied on the top level of a query and not property specific. Use the `properties` attribute of the schema to match against nested fields. + There are also methods on the Criteria class for geospatial queries. Here is a listing but look at the section on <> to see them in action. @@ -1467,7 +1469,65 @@ WARNING: Indexes are only used if the collation used for the operation and the i [[mongo.jsonSchema]] === JSON Schema -As of version 3.6 MongoDB supports collections that validate ``Document``s against a provided JSON Schema. The schema itself and both validation action and level can be defined when creating the collection. +As of version 3.6 MongoDB supports collections that validate ``Document``s against a provided JSON Schema. +The schema itself and both validation action and level can be defined when creating the collection. + +.Sample JSON schema +==== +[source,json] +---- +{ + "type": "object", <1> + + "required": [ "firstname", "lastname" ], <2> + + "properties": { <3> + + "firstname": { <4> + "type": "string", + "enum": [ "luke", "han" ] + }, + "address": { <5> + "type": "object", + "properties": { + "postCode": { "type": "string", "minLength": 4, "maxLength": 5 } + } + } + } +} +---- +<1> JSON schema documents always describe a whole document from its root. A schema is a schema object itself that can contain +embedded schema objects describing properties and subdocuments. +<2> `required` is a property describing which properties are required in a document. It can be specified optionally along of other +schema constraints. See MongoDB's documentation on https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/#available-keywords[available keywords]. +<3> `properties` is related to a schema object describing an `object` type. It contains property-specific schema constraints. +<4> `firstname` specifies constrains for the `firsname` field inside the document. Here it's a string-based properties declaring + possible field values. +<5> `address` is a subdocument defining a schema for values in its `postCode` field. +==== + +You can provide a schema either by specifying a schema document (i.e. using the `Document` API by parsing or building a document object) or by building it with Spring Data's JSON schema utilities in `org.springframework.data.mongodb.core.schema`. `MongoJsonSchema` is the entry point for all JSON schema-related operations. + +.Creating a JSON schema +==== +[source,java] +---- +MongoJsonSchema.builder() <1> + .required("firstname", "lastname") <2> + + .properties( + string("firstname").possibleValues("luke", "han"), <3> + + object("address") + .properties(string("postCode").minLength(4).maxLength(5))) + + .build(); <4> +---- +<1> Obtain a schema builder to configure the schema with a fluent API. +<2> Configure required properties. +<3> Configure the String-typed `firstname` field allowing only `luke` and `han` values. Properties can be typed or untyped. Use a static import of `JsonSchemaProperty` to make the syntax slightly more compact and to get entrypoints like `string(…)`. +<4> Build the schema object. Use the schema to either create a collection or <>. +==== `CollectionOptions` provides the entry point to schema support for collections. @@ -1475,21 +1535,100 @@ As of version 3.6 MongoDB supports collections that validate ``Document``s again ==== [source,java] ---- -// TODO: add sample here! +MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build(); + +template.createCollection(Person.class, CollectionOptions.empty().schema(schema)); ---- ==== -Additionally it is also possible to query any collection for documents that match a given structure defined by a JSON Schema. +You can use a schema to query any collection for documents that match a given structure defined by a JSON schema. -.Query collation for Documents matching a `$jsonSchema` +.Query for Documents matching a `$jsonSchema` ==== [source,java] ---- -// TODO: add sample here! +MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build(); + +template.find(query(matchingDocumentStructure(schema)), Person.class); ---- ==== -NOTE: `$jsonSchema` can only be applied on the top level of a query and not property specific. Use the `properties` attribute of the schema to match against nested fields. +[cols="3,1,6", options="header"] +.Supported JSON schema types +|=== +| Schema Type +| Java Type +| Schema Properties + +| `untyped` +| - +| `description`, generated `description`, `enum`, `allOf`, `anyOf`, `oneOf`, `not` + +| `object` +| `Object` +| `required`, `additionalProperties`, `properties`, `minProperties`, `maxProperties`, `patternProperties` + +| `array` +| any array except `byte[]` +| `uniqueItems`, `additionalItems`, `items`, `minItems`, `maxItems` + +| `string` +| `String` +| `minLength`, `maxLentgth`, `pattern` + +| `int` +| `int`, `Integer` +| `multipleOf`, `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum` + +| `long` +| `long`, `Long` +| `multipleOf`, `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum` + +| `double` +| `float`, `Float`, `double`, `Double` +| `multipleOf`, `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum` + +| `decimal` +| `BigDecimal` +| `multipleOf`, `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum` + +| `number` +| `Number` +| `multipleOf`, `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum` + +| `binData` +| `byte[]` +| + +| `boolean` +| `boolean`, `Boolean` +| + +| `null` +| `null` +| + +| `objectId` +| `ObjectId` +| + +| `date` +| `java.util.Date` +| + +| `timestamp` +| `BsonTimestamp` +| + +| `regex` +| `java.util.regex.Pattern` +| + +|=== + +NOTE: `untyped` is a generic type that is inherited by all typed schema types providing all `untyped` schema properties to typed schema types. + +For more information, see https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/#op._S_jsonSchema[$jsonSchema]. [[mongo.query.fluent-template-api]] === Fluent Template API