UNPKG

@mysql/xdevapi

Version:

MySQL Connector/Node.js - A Node.js driver for MySQL using the X Protocol and X DevAPI.

337 lines (263 loc) 12.2 kB
### Id generation When adding documents to a collection, if a document does not contain an `_id`, it will be automatically assigned a sequential UUID-like value. One can, however, override this behavior by providing a static `_id` for each document. #### Using automatically assigned values ```javascript const mysqlx = require('@mysql/xdevapi'); const docs = []; mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { return session.getSchema('mySchema').createCollection('myCollection'); }) .then(collection => { return collection.add({ name: 'foo' }) .execute() .then(() => { return collection.find() .execute(doc => docs.push(doc)); }) }) .then(() => { // the `_id` value is just an example in this case console.log(docs); // [{ _id: '00005a640138000000000000002c', name: 'foo' }] }); ``` #### Using static values ```javascript const mysqlx = require('@mysql/xdevapi'); const docs = []; mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { return session.getSchema('mySchema').createCollection('myCollection'); }) .then(collection => { return collection.add({ _id: 1, name: 'foo' }) .execute() .then(() => { return collection.find() .execute(doc => docs.push(doc)); }); }) .then(() => { console.log(docs); // [{ _id: 1, name: 'foo' }] }); ``` ### Single document CRUD The connector provides a set of utility methods that can be used to add, remove, replace or retrieve a single specific document via its `_id` property. Consider a collection `mySchema.myCollection` containing the following documents: ```json [{ "_id": "1", "name": "foo" }, { "_id": "2", "name": "bar" }] ``` The following scenarios are possible. #### Replacing a single document If a document with a given `_id` already exists in the database, it can be replaced via the {@link module:Collection#replaceOne|`Collection.replaceOne()`} method. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.replaceOne('1', { name: 'baz', age: 23 }) .then(result => { console.log(result.getAffectedItemsCount()); // 1 return collection.find() .execute(); }); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', age: 23 }, { _id: '2', name: 'bar' } ] }); ``` If no such document exists, the method will neither fail nor have any effect. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection') return collection.replaceOne('3', { name: 'baz', age: 23 }) .then(result => { console.log(result.getAffectedItemsCount()); // 0 return collection.find() .execute(); }); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', name: 'foo' }, { _id: '2', name: 'bar' } ] }); ``` If the replacement document in the second argument contains an `_id` property and its value is different from the id value provided as the first argument, an error will be reported, regardless of whether documents with either of those ids already exist in the collection or not. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection') return collection.replaceOne('1', { _id: '2', name: 'baz', age: 23 }) }) .catch(err => { console.log(err.message); // Replacement document has an _id that is different than the matched document. }); ``` #### Creating or updating a single document The connector also provides an additional utility method - {@link module:Collection#addOrReplaceOne|`Collection.addOrReplaceOne()`} - that allows to seamlessly either create a document with a given `_id` and properties or automatically replace an existing matching document. So, if a document with the given `_id` already exists in a collection, the behavior is the same as with {@link module:Collection#replaceOne|`Collection.replaceOne()`}. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.addOrReplaceOne('1', { name: 'baz', age: 23 }) .then(result => { // the existing row is re-created (leading to two different operations) // see https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html console.log(result.getAffectedItemsCount()); // 2 return collection.find() .execute(); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', name: 'baz', age: 23 }, { _id: '2', name: 'bar' } ] }); }) ``` If no such document exists, a new one will be created. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.addOrReplaceOne('3', { name: 'baz', age: 23 }) .then(result => { console.log(result.getAffectedItemsCount()); // 1 return collection.find() .execute(); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', name: 'foo' }, { _id: '2', name: 'bar' }, { _id: '3', name: 'baz', age: 23 } ] }); }); ``` Just like {@link module:Collection#replaceOne|`replaceOne()`}, when calling {@link module:Collection#addOrReplaceOne|`addOrReplaceOne()`}, if the replacement document in the second argument contains an `_id` property and its value is different from the id value provided as the first argument, an error will be reported, regardless of whether documents with either of those ids already exist in the collection or not. ```js const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.addOrReplaceOne('3', { _id: '4', name: 'baz', age: 23 }) }) .catch(err => { console.log(err.message); // Replacement document has an _id that is different than the matched document. }); ``` When additional unique key constraints exist for a collection, a few additional scenarios are brought up. Assuming, the `name` property has a unique key constraint established by a [auto-generated column](https://dev.mysql.com/doc/refman/8.0/en/create-table-secondary-indexes.html#json-column-indirect-index). ```sql ALTER TABLE mySchema.myCollection ADD COLUMN name VARCHAR(3) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$.name'))) VIRTUAL UNIQUE KEY NOT NULL ``` Existing documents will be updated with the given properties, provided that there are no unique key constraint violations with other documents. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.addOrReplaceOne('1', { name: 'baz' }) .then(result => { // the existing row is re-created (leading to two different operations) // see https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html console.log(result.getAffectedItemsCount()); // 2 return collection.find() .execute(); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', name: 'baz' }, { _id: '2', name: 'bar' } ] }); }); ``` Unique key values themselves can also be updated with the same restrictions. ```javascript const mysqlx = require('@mysql/xdevapi'); const docs = []; mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.addOrReplaceOne('1', { name: 'foo', age: 23 }) .then(result => { // the existing row is re-created (leading to two different operations) // see https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html console.log(result.getAffectedItemsCount()); // 2 return collection.find() .execute(); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', name: 'foo', age: 23 }, { _id: '2', name: 'bar' } ] }); }); ``` Unique key constraint violations will, of course, result in an error. ```javascript const mysqlx = require('@mysql/xdevapi') mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { return session.getSchema('mySchema').getCollection('myCollection').addOrReplaceOne('1', { name: 'bar' }); }) .catch(err => { console.log(err.message); }) ``` #### Retrieving a single document There is also an utility method to retrieve a single document from a collection, given its `id` - `Collection.getOne()`. The method returns a `Promise` which resolves to the document instance (in the form of a literal object), if it exists or `null`, if it does not. ```javascript const mysqlx = require('@mysql/xdevapi') mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { return session.getSchema('mySchema').getCollection('myCollection').getOne('1'); }) .then(doc => { console.log(doc); // { _id: '1', name: 'foo' } }); ``` ```javascript const mysqlx = require('@mysql/xdevapi') mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { return session.getSchema('mySchema').getCollection('myCollection').getOne('3'); }) .then(doc => { console.log(doc); // null }); ``` #### Removing a single document One can also remove a specific document from a collection given its `id` - `Collection.removeOne()`. If no such document exists, the operation succeeds, but nothing really happens. ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.removeOne('1') .then(result => { console.log(result.getAffectedItemsCount()); // 1 return collection.find() .execute(); }) .then(result => { console.log(result.fetchAll()); // [ { _id: '2', name: 'bar' } ] }); }); ``` ```javascript const mysqlx = require('@mysql/xdevapi'); mysqlx.getSession('mysqlx://localhost:33060/mySchema') .then(session => { const collection = session.getSchema('mySchema').getCollection('myCollection'); return collection.removeOne('3') .then(result => { console.log(result.getAffectedItemsCount()); // 0 return collection.find() .execute(); }) }) .then(result => { console.log(result.fetchAll()); // [ { _id: '1', name: 'foo' }, { _id: '2', name: 'bar' } ] }); ```