Edit Page

.addToCollection()

Add one or more existing child records to the specified collection (e.g. the comments of BlogPost #4).

await Something.addToCollection(parentId, association)
.members(childIds);

Usage

Argument Type Details
1 parentId or The primary key value(s) (i.e. ids) for the parent record(s).
Must be a number or string (e.g. '507f191e810c19729de860ea' or 49).
Alternatively, an array of numbers or strings may be specified (e.g. ['507f191e810c19729de860ea', '14832ace0c179de897'] or [49, 32, 37]). In this case, all of the child records will be added to the appropriate collection of each parent record.
2 association The name of the plural ("collection") association (e.g. "pets").
3 childIds The primary key values (i.e. ids) of the child records to add. Note that this does not create these child records, it just links them to the specified parent(s).
Errors
Name Type When?
UsageError Thrown if something invalid was passed in.
AdapterError Thrown if something went wrong in the database adapter.
Error Thrown if anything else unexpected happens.

See Concepts > Models and ORM > Errors for examples of negotiating errors in Sails and Waterline.

Example

For user 3, add pets 99 and 98 to the "pets" collection:

await User.addToCollection(3, 'pets')
.members([99,98]);

If either user record already has one of those pets in its "pets", then we just silently skip over it.

Edge cases

  • If an empty array of child ids is provided, then this is a no-op.
  • If an empty array of parent ids is provided, then this is a no-op.

  • If the parent id (or any one of the parent ids, if specified as an array) does not actually correspond with an existing, persisted record, the exact behavior depends on what kind of association this is:

    • If this collection is a 1-way association, or a 2-way association where the other side is plural (many-to-many), then Waterline pretends like the parent record(s) exist anyways, tracking their relationships as prearranged, "aspirational" junction records in the database.
    • If this is a 2-way association where the other side is singular (one-to-many), then the missing parent records are simply ignored.
  • Along the same lines, if one of the child ids does not actually correspond with an existing, persisted record, then:

    • If this is a 1-way association, or a 2-way association where the other side is plural (many-to-many), then Waterline pretends like these hypothetical child record(s) exist anyways, tracking their relationships as prearranged, "aspirational" junction records in the database.
    • If this is a 2-way association where the other side is singular (one-to-many), then the missing child records are simply ignored.
  • If a parent record's collection already has one or more of these children as members, then, for performance reasons, those memberships might be tracked again (e.g. stored in your database's join table multiple times). In most cases, that's OK, since it usually doesn't affect future queries (for example, when populating the relevant parent record's collection, the double-tracked relationship will not result in the child being listed more than once). If you do need to prevent duplicate join table records, there's an easy way to work around this—assuming you are using a relational database like MySQL or PostgreSQL, then you can create a multi-column index on your join table. Doing so will cause queries like this to result in an AdapterError with code: 'E_UNIQUE'.

Notes

  • This method can be used with await, promise chaining, or traditional Node callbacks.
  • If the association is "2-way" (meaning it has via) then the child records will be modified accordingly. If the attribute on the other side is singular, then each child record's foreign key will be changed. If it's plural, then each child record's collection will be modified accordingly.
  • In addition, if the via points at a singular ("model") attribute on the other side, then .addToCollection() will "steal" these child records if necessary. For example, imagine you have an Employee model with this plural ("collection") attribute: involvedInPurchases: { collection: 'Purchase', via: 'cashier' }. If you executed Employee.addToCollection(7, 'involvedInPurchases', [47]) to assign this purchase to employee #7 (Dolly), but purchase #47 was already associated with a different employee (e.g. #12, Motoki), then this would "steal" the purchase from Motoki and give it to Dolly. In other words, if you executed Employee.find([7, 12]).populate('involvedInPurchases'), Dolly's involvedInPurchases array would contain purchase #47 and Motoki's would not.

Is something missing?

If you notice something we've missed or could be improved on, please follow this link and submit a pull request to the sails repo. Once we merge it, the changes will be reflected on the website the next time it is deployed.

Sails logo
  • Home
  • Get started
  • Support
  • Documentation
  • Documentation

For a better experience on sailsjs.com, update your browser.

Check out the full Sailsconf 2022 playlist on Youtube

Tweet Follow @sailsjs

Documentation

Reference Concepts App structure | Upgrading Contribution guide | Tutorials More

Reference

  • Application
    • Advanced usage
      • Lifecycle
      • sails.LOOKS_LIKE_ASSET_RX
      • sails.getActions()
      • sails.getRouteFor()
      • sails.lift()
      • sails.load()
      • sails.lower()
      • sails.registerAction()
      • sails.registerActionMiddleware()
      • sails.reloadActions()
      • sails.renderView()
      • sails.request()
      • sails.getBaseUrl()
    • sails.config.custom
    • sails.getDatastore()
    • sails.getUrlFor()
    • sails.log()
  • Blueprint API
    • add to
    • create
    • destroy
    • find one
    • find where
    • populate where
    • remove from
    • replace
    • update
  • Command-line interface
    • sails --version
    • sails console
    • sails debug
    • sails generate
    • sails inspect
    • sails lift
    • sails new
  • Configuration
    • sails.config.*
    • sails.config.blueprints
    • sails.config.bootstrap()
    • sails.config.custom
    • sails.config.datastores
    • sails.config.globals
    • sails.config.http
    • sails.config.i18n
    • sails.config.log
    • sails.config.models
    • sails.config.policies
    • sails.config.routes
    • sails.config.security
    • sails.config.session
    • sails.config.sockets
    • sails.config.views
  • Request (`req`)
    • req._startTime
    • req.body
    • req.cookies
    • req.fresh
    • req.headers
    • req.hostname
    • req.ip
    • req.ips
    • req.isSocket
    • req.method
    • req.options
    • req.originalUrl
    • req.params
    • req.path
    • req.protocol
    • req.query
    • req.secure
    • req.signedCookies
    • req.socket
    • req.subdomains
    • req.url
    • req.wantsJSON
    • req.xhr
    • req.accepts()
    • req.acceptsCharsets()
    • req.acceptsLanguages()
    • req.allParams()
    • req.file()
    • req.get()
    • req.is()
    • req.param()
    • req.setLocale()
    • req.setTimeout()
    • req.host
  • Response (`res`)
    • res.attachment()
    • res.badRequest()
    • res.clearCookie()
    • res.cookie()
    • res.forbidden()
    • res.get()
    • res.json()
    • res.jsonp()
    • res.location()
    • res.notFound()
    • res.ok()
    • res.redirect()
    • res.send()
    • res.serverError()
    • res.set()
    • res.status()
    • res.type()
    • res.view()
    • res.negotiate()
  • Waterline (ORM)
    • Datastores
      • .driver
      • .manager
      • .leaseConnection()
      • .sendNativeQuery()
      • .transaction()
    • Models
      • .addToCollection()
      • .archive()
      • .archiveOne()
      • .avg()
      • .count()
      • .create()
      • .createEach()
      • .destroy()
      • .destroyOne()
      • .find()
      • .findOne()
      • .findOrCreate()
      • .getDatastore()
      • .removeFromCollection()
      • .replaceCollection()
      • .stream()
      • .sum()
      • .update()
      • .updateOne()
      • .validate()
      • .native()
      • .query()
    • Queries
      • .catch()
      • .decrypt()
      • .exec()
      • .fetch()
      • .intercept()
      • .limit()
      • .meta()
      • .populate()
      • .skip()
      • .sort()
      • .then()
      • .tolerate()
      • .toPromise()
      • .usingConnection()
      • .where()
    • Records
      • .toJSON()
  • WebSockets
    • Resourceful PubSub
      • .getRoomName()
      • .publish()
      • .subscribe()
      • .unsubscribe()
    • sails.sockets
      • .addRoomMembersToRooms()
      • .blast()
      • .broadcast()
      • .getId()
      • .join()
      • .leave()
      • .leaveAll()
      • .removeRoomMembersFromRooms()
      • sails.sockets.id()
    • Socket client
      • io.sails
      • io.socket
      • SailsSocket
        • Methods
        • Properties
      • io.socket.delete()
      • io.socket.get()
      • io.socket.off()
      • io.socket.on()
      • io.socket.patch()
      • io.socket.post()
      • io.socket.put()
      • io.socket.request()

Built with Love

The Sails framework is built by a web & mobile shop in Austin, TX, with the help of our contributors. We created Sails in 2012 to assist us on Node.js projects. Naturally we open-sourced it. We hope it makes your life a little bit easier!

Sails:
  • What is Sails?
  • Community
  • News
  • For business
About:
  • Our company
  • Security
  • Legal
  • Logos/artwork
Help:
  • Get started
  • Documentation
  • Docs
  • Contribute
  • Take a class

© 2012-2022 The Sails Company. 
The Sails framework is free and open-source under the MIT License. 
Illustrations by Edamame.