diff --git a/doc/3/controllers/collection/create/index.md b/doc/3/controllers/collection/create/index.md
new file mode 100644
index 00000000..856848fb
--- /dev/null
+++ b/doc/3/controllers/collection/create/index.md
@@ -0,0 +1,64 @@
+---
+code: true
+type: page
+title: create
+description: Creates a new collection
+---
+
+# create
+
+Creates a new [collection](/core/2/guides/essentials/store-access-data) in Kuzzle via the persistence engine, in the provided index.
+
+You can also provide an optional data mapping that allows you to exploit the full capabilities of our
+persistent data storage layer, [ElasticSearch](https://www.elastic.co/elastic-stack) (check here the [mapping capabilities of ElasticSearch](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/mapping.html)).
+
+This method will only update the mapping if the collection already exists.
+
+
+
+---
+
+## Arguments
+
+```java
+public CompletableFuture create(
+ final String index,
+ final String collection,
+ final ConcurrentHashMap mapping)
+throws NotConnectedException, InternalException
+
+public CompletableFuture create(
+ final String index,
+ final String collection)
+throws NotConnectedException, InternalException
+```
+
+| Arguments | Type | Description |
+| ------------------ | -------------------------------------------- | --------------------------------- |
+| `index` | String
| Index |
+| `collection` | String
| Collection |
+| `mapping` | ConcurrentHashMap
| Describes the data mapping to associate to the new collection, using Elasticsearch [mapping format](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/mapping.html) |
+
+---
+
+### mapping
+
+A `ConcurrentHashMap` representing the data mapping of the collection.
+
+The mapping must have a root field `properties` that contain the mapping definition:
+
+```java
+ ConcurrentHashMap mapping = new ConcurrentHashMap<>();
+ ConcurrentHashMap properties = new ConcurrentHashMap<>();
+ ConcurrentHashMap field = new ConcurrentHashMap<>();
+
+ field.put("type", "keyword");
+ properties.put("field", field);
+ mapping.put("properties", properties);
+```
+
+More information about database mappings [here](/core/2/guides/essentials/database-mappings).
+
+## Usage
+
+<<< ./snippets/create.java
diff --git a/doc/3/controllers/collection/create/snippets/create.java b/doc/3/controllers/collection/create/snippets/create.java
new file mode 100644
index 00000000..2e59f164
--- /dev/null
+++ b/doc/3/controllers/collection/create/snippets/create.java
@@ -0,0 +1,10 @@
+ ConcurrentHashMap mapping = new ConcurrentHashMap<>();
+ ConcurrentHashMap properties = new ConcurrentHashMap<>();
+ ConcurrentHashMap license = new ConcurrentHashMap<>();
+
+ license.put("type", "keyword");
+ properties.put("license", license);
+ mapping.put("properties", properties);
+
+ kuzzle.getCollectionController().create("nyc-open-data", "yellow-taxi", mapping)
+ .get();
\ No newline at end of file
diff --git a/doc/3/controllers/collection/create/snippets/create.test.yml b/doc/3/controllers/collection/create/snippets/create.test.yml
new file mode 100644
index 00000000..ad25ec5b
--- /dev/null
+++ b/doc/3/controllers/collection/create/snippets/create.test.yml
@@ -0,0 +1,9 @@
+name: collection#create
+description: Creates a new collection
+hooks:
+ before: |
+ curl -XDELETE kuzzle:7512/nyc-open-data
+ curl -XPOST kuzzle:7512/nyc-open-data/_create
+ after:
+template: default
+expected: Success
\ No newline at end of file
diff --git a/doc/3/controllers/document/m-update/snippets/m-update.test.yml b/doc/3/controllers/document/m-update/snippets/m-update.test.yml
index 29ccba1f..b14ef60a 100644
--- a/doc/3/controllers/document/m-update/snippets/m-update.test.yml
+++ b/doc/3/controllers/document/m-update/snippets/m-update.test.yml
@@ -10,5 +10,5 @@ hooks:
after:
template: print-result-array
expected:
- - "id=some-id, status=200"
- - "id=some-id2, status=200"
\ No newline at end of file
+ - "id=some-id, _version=2, status=200"
+ - "id=some-id2, _version=2, status=200"
\ No newline at end of file
diff --git a/src/main/java/io/kuzzle/sdk/API/Controllers/CollectionController.java b/src/main/java/io/kuzzle/sdk/API/Controllers/CollectionController.java
index cdf96dbe..78c410a3 100644
--- a/src/main/java/io/kuzzle/sdk/API/Controllers/CollectionController.java
+++ b/src/main/java/io/kuzzle/sdk/API/Controllers/CollectionController.java
@@ -40,6 +40,51 @@ public CompletableFuture exists(
(response) -> (Boolean) response.result);
}
+ /**
+ * Creates a collection in a given index.
+ *
+ * @param index
+ * @param collection
+ * @param mappings
+ * @return a CompletableFuture
+ * @throws NotConnectedException
+ * @throws InternalException
+ */
+ public CompletableFuture create(
+ final String index,
+ final String collection,
+ final ConcurrentHashMap mappings) throws NotConnectedException, InternalException {
+
+ final KuzzleMap query = new KuzzleMap();
+
+ query
+ .put("index", index)
+ .put("collection", collection)
+ .put("controller", "collection")
+ .put("action", "create")
+ .put("body", mappings != null ? new KuzzleMap(mappings) : null);
+
+ return kuzzle
+ .query(query)
+ .thenApplyAsync((response) -> null);
+ }
+
+ /**
+ * Creates a collection in a given index.
+ *
+ * @param index
+ * @param collection
+ * @return a CompletableFuture
+ * @throws NotConnectedException
+ * @throws InternalException
+ */
+ public CompletableFuture create(
+ final String index,
+ final String collection) throws NotConnectedException, InternalException {
+
+ return this.create(index, collection, null);
+ }
+
/**
* Get collection mapping
*
diff --git a/src/test/java/io/kuzzle/test/API/Controllers/CollectionTest.java b/src/test/java/io/kuzzle/test/API/Controllers/CollectionTest.java
index 99523b49..dca7b1c6 100644
--- a/src/test/java/io/kuzzle/test/API/Controllers/CollectionTest.java
+++ b/src/test/java/io/kuzzle/test/API/Controllers/CollectionTest.java
@@ -12,6 +12,8 @@
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
+import java.util.concurrent.ConcurrentHashMap;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.spy;
@@ -50,6 +52,72 @@ public void existsCollectionShouldThrowWhenNotConnected() throws NotConnectedExc
kuzzleMock.getCollectionController().exists(index, collection);
}
+ @Test
+ public void createCollectionTestA() throws NotConnectedException, InternalException {
+
+ Kuzzle kuzzleMock = spy(new Kuzzle(networkProtocol));
+ String index = "nyc-open-data";
+ String collection = "yellow-taxi";
+
+ ArgumentCaptor arg = ArgumentCaptor.forClass(KuzzleMap.class);
+
+ kuzzleMock.getCollectionController().create(index, collection);
+ Mockito.verify(kuzzleMock, Mockito.times(1)).query(arg.capture());
+
+ assertEquals((arg.getValue()).getString("controller"), "collection");
+ assertEquals((arg.getValue()).getString("action"), "create");
+ assertEquals((arg.getValue()).getString("collection"), "yellow-taxi");
+ assertEquals((arg.getValue()).getString("index"), "nyc-open-data");
+ }
+
+ @Test
+ public void createCollectionTestB() throws NotConnectedException, InternalException {
+
+ Kuzzle kuzzleMock = spy(new Kuzzle(networkProtocol));
+ String index = "nyc-open-data";
+ String collection = "yellow-taxi";
+
+ ArgumentCaptor arg = ArgumentCaptor.forClass(KuzzleMap.class);
+
+ ConcurrentHashMap mapping = new ConcurrentHashMap<>();
+ ConcurrentHashMap properties = new ConcurrentHashMap<>();
+ ConcurrentHashMap license = new ConcurrentHashMap<>();
+
+ license.put("type", "keyword");
+ properties.put("license", license);
+ mapping.put("properties", properties);
+
+ kuzzleMock.getCollectionController().create(index, collection, mapping);
+ Mockito.verify(kuzzleMock, Mockito.times(1)).query(arg.capture());
+
+ assertEquals((arg.getValue()).getString("controller"), "collection");
+ assertEquals((arg.getValue()).getString("action"), "create");
+ assertEquals((arg.getValue()).getString("index"), "nyc-open-data");
+ assertEquals((arg.getValue()).getString("collection"), "yellow-taxi");
+ assertEquals((
+ (ConcurrentHashMap) (
+ (ConcurrentHashMap) (
+ ((ConcurrentHashMap)
+ ((arg.getValue())
+ .get("body")))
+ .get("properties")))
+ .get("license"))
+ .get("type").toString(), "keyword");
+ }
+
+ @Test(expected = NotConnectedException.class)
+ public void createCollectionThrowWhenNotConnected() throws NotConnectedException, InternalException {
+
+ AbstractProtocol fakeNetworkProtocol = Mockito.mock(WebSocket.class);
+ Mockito.when(fakeNetworkProtocol.getState()).thenAnswer((Answer) invocation -> ProtocolState.CLOSE);
+
+ Kuzzle kuzzleMock = spy(new Kuzzle(fakeNetworkProtocol));
+ String index = "nyc-open-data";
+ String collection = "yellow-taxi";
+
+ kuzzleMock.getCollectionController().create(index, collection);
+ }
+
@Test
public void getMappingCollectionTest() throws NotConnectedException, InternalException {