--- title: Collections description: Documentation on how to use Meteor's database collections. --- Meteor stores data in *collections*. To get started, declare a collection with `new Mongo.Collection`. {% apibox "Mongo.Collection" %} Calling this function is analogous to declaring a model in a traditional ORM (Object-Relation Mapper)-centric framework. It sets up a *collection* (a storage space for records, or "documents") that can be used to store a particular type of information, like users, posts, scores, todo items, or whatever matters to your application. Each document is a EJSON object. It includes an `_id` property whose value is unique in the collection, which Meteor will set when you first create the document. ```js // Common code on client and server declares a DDP-managed Mongo collection. const Chatrooms = new Mongo.Collection('chatrooms'); const Messages = new Mongo.Collection('messages'); ``` The function returns an object with methods to [`insert`](#insert) documents in the collection, [`update`](#update) their properties, and [`remove`](#remove) them, and to [`find`](#find) the documents in the collection that match arbitrary criteria. The way these methods work is compatible with the popular Mongo database API. The same database API works on both the client and the server (see below). ```js // Return an array of my messages. const myMessages = Messages.find({ userId: Meteor.userId() }).fetch(); // Create a new message. Messages.insert({ text: 'Hello, world!' }); // Mark my first message as important. Messages.update(myMessages[0]._id, { $set: { important: true } }); ``` If you pass a `name` when you create the collection, then you are declaring a persistent collection — one that is stored on the server and seen by all users. Client code and server code can both access the same collection using the same API. Specifically, when you pass a `name`, here's what happens: * On the server (if you do not specify a `connection`), a collection with that name is created on a backend Mongo server. When you call methods on that collection on the server, they translate directly into normal Mongo operations (after checking that they match your [access control rules](#allow)). * On the client (and on the server if you specify a `connection`), a Minimongo instance is created. Minimongo is essentially an in-memory, non-persistent implementation of Mongo in pure JavaScript. It serves as a local cache that stores just the subset of the database that this client is working with. Queries ([`find`](#find)) on these collections are served directly out of this cache, without talking to the server. * When you write to the database on the client ([`insert`](#insert), [`update`](#update), [`remove`](#remove)), the command is executed locally immediately, and, simultaneously, it's sent to the server and executed there too. This happens via [stubs](#meteor_methods), because writes are implemented as methods. > When, on the server, you write to a collection which has a specified `connection` to another server, it sends the corresponding method to the other server and receives the changed values back from it over DDP. Unlike on the client, it does not execute the write locally first. If you pass a name to a client-only collection, it will not be synchronized with the server and you need to populate the collection "manually" using the low-level publication interface (`added/changed/removed`). See [`added`](#publish_added) for more information. If you pass `null` as the `name`, then you're creating a local collection. It's not synchronized anywhere; it's just a local scratchpad that supports Mongo-style [`find`](#find), [`insert`](#insert), [`update`](#update), and [`remove`](#remove) operations. (On both the client and the server, this scratchpad is implemented using Minimongo.) By default, Meteor automatically publishes every document in your collection to each connected client. To turn this behavior off, remove the `autopublish` package, in your terminal: ```bash meteor remove autopublish ``` and instead call [`Meteor.publish`](#meteor_publish) to specify which parts of your collection should be published to which users. ```js // Create a collection called `Posts` and put a document in it. The document // will be immediately visible in the local copy of the collection. It will be // written to the server-side database a fraction of a second later, and a // fraction of a second after that, it will be synchronized down to any other // clients that are subscribed to a query that includes it (see // `Meteor.subscribe` and `autopublish`). const Posts = new Mongo.Collection('posts'); Posts.insert({ title: 'Hello world', body: 'First post' }); // Changes are visible immediately—no waiting for a round trip to the server. assert(Posts.find().count() === 1); // Create a temporary, local collection. It works just like any other collection // but it doesn't send changes to the server, and it can't receive any data from // subscriptions. const Scratchpad = new Mongo.Collection; for (let i = 0; i < 10; i += 1) { Scratchpad.insert({ number: i * 2 }); } assert(Scratchpad.find({ number: { $lt: 9 } }).count() === 5); ``` Generally, you'll assign `Mongo.Collection` objects in your app to global variables. You can only create one `Mongo.Collection` object for each underlying Mongo collection. If you specify a `transform` option to the `Collection` or any of its retrieval methods, documents are passed through the `transform` function before being returned or passed to callbacks. This allows you to add methods or otherwise modify the contents of your collection from their database representation. You can also specify `transform` on a particular `find`, `findOne`, `allow`, or `deny` call. Transform functions must return an object and they may not change the value of the document's `_id` field (though it's OK to leave it out). ```js // An animal class that takes a document in its constructor. class Animal { constructor(doc) { _.extend(this, doc); } makeNoise() { console.log(this.sound); } } // Define a collection that uses `Animal` as its document. const Animals = new Mongo.Collection('animals', { transform: (doc) => new Animal(doc) }); // Create an animal and call its `makeNoise` method. Animals.insert({ name: 'raptor', sound: 'roar' }); Animals.findOne({ name: 'raptor' }).makeNoise(); // Prints 'roar' ``` `transform` functions are not called reactively. If you want to add a dynamically changing attribute to an object, do it with a function that computes the value at the time it's called, not by computing the attribute at `transform` time. {% pullquote warning %} In this release, Minimongo has some limitations: * `$pull` in modifiers can only accept certain kinds of selectors. * `findAndModify`, aggregate functions, and map/reduce aren't supported. All of these will be addressed in a future release. For full Minimongo release notes, see packages/minimongo/NOTES in the repository. {% endpullquote %} {% pullquote warning %} Minimongo doesn't currently have indexes. It's rare for this to be an issue, since it's unusual for a client to have enough data that an index is worthwhile. {% endpullquote %} Read more about collections and how to use them in the [Collections](http://guide.meteor.com/collections.html) article in the Meteor Guide. {% apibox "Mongo.Collection#find" %} `find` returns a cursor. It does not immediately access the database or return documents. Cursors provide `fetch` to return all matching documents, `map` and `forEach` to iterate over all matching documents, and `observe` and `observeChanges` to register callbacks when the set of matching documents changes. Cursors also implement ES2015's [iteration protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols). {% pullquote warning %} Collection cursors are not query snapshots. If the database changes between calling `Collection.find` and fetching the results of the cursor, or while fetching results from the cursor, those changes may or may not appear in the result set. {% endpullquote %} Cursors are a reactive data source. On the client, the first time you retrieve a cursor's documents with `fetch`, `map`, or `forEach` inside a reactive computation (eg, a template or [`autorun`](#tracker_autorun)), Meteor will register a dependency on the underlying data. Any change to the collection that changes the documents in a cursor will trigger a recomputation. To disable this behavior, pass `{reactive: false}` as an option to `find`. Note that when `fields` are specified, only changes to the included fields will trigger callbacks in `observe`, `observeChanges` and invalidations in reactive computations using this cursor. Careful use of `fields` allows for more fine-grained reactivity for computations that don't depend on an entire document. On the client, there will be a period of time between when the page loads and when the published data arrives from the server during which your client-side collections will be empty. {% apibox "Mongo.Collection#findOne" %} Equivalent to [`find`](#find)`(selector, options).`[`fetch`](#fetch)`()[0]` with `options.limit = 1`. {% apibox "Mongo.Collection#insert" %} Add a document to the collection. A document is just an object, and its fields can contain any combination of EJSON-compatible datatypes (arrays, objects, numbers, strings, `null`, true, and false). `insert` will generate a unique ID for the object you pass, insert it in the database, and return the ID. When `insert` is called from untrusted client code, it will be allowed only if passes any applicable [`allow`](#allow) and [`deny`](#deny) rules. On the server, if you don't provide a callback, then `insert` blocks until the database acknowledges the write, or throws an exception if something went wrong. If you do provide a callback, `insert` still returns the ID immediately. Once the insert completes (or fails), the callback is called with error and result arguments. In an error case, `result` is undefined. If the insert is successful, `error` is undefined and `result` is the new document ID. On the client, `insert` never blocks. If you do not provide a callback and the insert fails on the server, then Meteor will log a warning to the console. If you provide a callback, Meteor will call that function with `error` and `result` arguments. In an error case, `result` is undefined. If the insert is successful, `error` is undefined and `result` is the new document ID. Example: ```js const groceriesId = Lists.insert({ name: 'Groceries' }); Items.insert({ list: groceriesId, name: 'Watercress' }); Items.insert({ list: groceriesId, name: 'Persimmons' }); ``` {% apibox "Mongo.Collection#update" %} Modify documents that match `selector` according to `modifier` (see [modifier documentation](#modifiers)). The behavior of `update` differs depending on whether it is called by trusted or untrusted code. Trusted code includes server code and method code. Untrusted code includes client-side code such as event handlers and a browser's JavaScript console. - Trusted code can modify multiple documents at once by setting `multi` to true, and can use an arbitrary [Mongo selector](#selectors) to find the documents to modify. It bypasses any access control rules set up by [`allow`](#allow) and [`deny`](#deny). The number of affected documents will be returned from the `update` call if you don't pass a callback. - Untrusted code can only modify a single document at once, specified by its `_id`. The modification is allowed only after checking any applicable [`allow`](#allow) and [`deny`](#deny) rules. The number of affected documents will be returned to the callback. Untrusted code cannot perform upserts, except in insecure mode. On the server, if you don't provide a callback, then `update` blocks until the database acknowledges the write, or throws an exception if something went wrong. If you do provide a callback, `update` returns immediately. Once the update completes, the callback is called with a single error argument in the case of failure, or a second argument indicating the number of affected documents if the update was successful. On the client, `update` never blocks. If you do not provide a callback and the update fails on the server, then Meteor will log a warning to the console. If you provide a callback, Meteor will call that function with an error argument if there was an error, or a second argument indicating the number of affected documents if the update was successful. Client example: ```js // When the 'give points' button in the admin dashboard is pressed, give 5 // points to the current player. The new score will be immediately visible on // everyone's screens. Template.adminDashboard.events({ 'click .give-points'() { Players.update(Session.get('currentPlayer'), { $inc: { score: 5 } }); } }); ``` Server example: ```js // Give the 'Winner' badge to each user with a score greater than 10. If they // are logged in and their badge list is visible on the screen, it will update // automatically as they watch. Meteor.methods({ declareWinners() { Players.update({ score: { $gt: 10 } }, { $addToSet: { badges: 'Winner' } }, { multi: true }); } }); ``` You can use `update` to perform a Mongo upsert by setting the `upsert` option to true. You can also use the [`upsert`](#upsert) method to perform an upsert that returns the `_id` of the document that was inserted (if there was one) in addition to the number of affected documents. {% apibox "Mongo.Collection#upsert" %} Modify documents that match `selector` according to `modifier`, or insert a document if no documents were modified. `upsert` is the same as calling `update` with the `upsert` option set to true, except that the return value of `upsert` is an object that contain the keys `numberAffected` and `insertedId`. (`update` returns only the number of affected documents.) {% apibox "Mongo.Collection#remove" %} Find all of the documents that match `selector` and delete them from the collection. The behavior of `remove` differs depending on whether it is called by trusted or untrusted code. Trusted code includes server code and method code. Untrusted code includes client-side code such as event handlers and a browser's JavaScript console. - Trusted code can use an arbitrary [Mongo selector](#selectors) to find the documents to remove, and can remove more than one document at once by passing a selector that matches multiple documents. It bypasses any access control rules set up by [`allow`](#allow) and [`deny`](#deny). The number of removed documents will be returned from `remove` if you don't pass a callback. As a safety measure, if `selector` is omitted (or is `undefined`), no documents will be removed. Set `selector` to `{}` if you really want to remove all documents from your collection. - Untrusted code can only remove a single document at a time, specified by its `_id`. The document is removed only after checking any applicable [`allow`](#allow) and [`deny`](#deny) rules. The number of removed documents will be returned to the callback. On the server, if you don't provide a callback, then `remove` blocks until the database acknowledges the write and then returns the number of removed documents, or throws an exception if something went wrong. If you do provide a callback, `remove` returns immediately. Once the remove completes, the callback is called with a single error argument in the case of failure, or a second argument indicating the number of removed documents if the remove was successful. On the client, `remove` never blocks. If you do not provide a callback and the remove fails on the server, then Meteor will log a warning to the console. If you provide a callback, Meteor will call that function with an error argument if there was an error, or a second argument indicating the number of removed documents if the remove was successful. Example (client): ```js // When the 'remove' button is clicked on a chat message, delete that message. Template.chat.events({ 'click .remove'() { Messages.remove(this._id); } }); ``` Example (server): ```js // When the server starts, clear the log and delete all players with a karma of // less than -2. Meteor.startup(() => { if (Meteor.isServer) { Logs.remove({}); Players.remove({ karma: { $lt: -2 } }); } }); ``` {% apibox "Mongo.Collection#createIndex" %} For efficient and performant queries you will sometimes need to define indexes other than the default `_id` field. You should add indexes to fields (or combinations of fields) you use to lookup documents in a collection. This is where `createIndex` comes into play. It takes in 2 objects. First is the key and index type specification (which field and how they should be indexed) and second are options like the index name. For details on how indexes work read the [MongoDB documentation](https://docs.mongodb.com/manual/indexes/). > Note that indexes only apply to server and MongoDB collection. They are not implemented for Minimongo at this time. Example defining a simple index on Players collection in Meteor: ```js Players.createIndex({ userId: 1 }, { name: 'user reference on players' }); ``` Sometimes you or a package might change an already established indexes. This might throw an error and prevent a startup. For cases where you can afford to re-build indexes or the change affect too many indexes you can set the `reCreateIndexOnOptionMismatch` to true in your `settings.json`: ```json { "packages": { "mongo": { "reCreateIndexOnOptionMismatch": true } } } ``` > You should use this option only when you are dealing with a change across many indexes and it is not feasible to fix them manually and you can afford the re-building of the indexes as this will destroy the old index and create a new one. Use this carefully. {% apibox "Mongo.Collection#allow" %} {% pullquote warning %} While `allow` and `deny` make it easy to get started building an app, it's harder than it seems to write secure `allow` and `deny` rules. We recommend that developers avoid `allow` and `deny`, and switch directly to custom methods once they are ready to remove `insecure` mode from their app. See [the Meteor Guide on security](https://guide.meteor.com/security.html#allow-deny) for more details. {% endpullquote %} When a client calls `insert`, `update`, or `remove` on a collection, the collection's `allow` and [`deny`](#deny) callbacks are called on the server to determine if the write should be allowed. If at least one `allow` callback allows the write, and no `deny` callbacks deny the write, then the write is allowed to proceed. These checks are run only when a client tries to write to the database directly, for example by calling `update` from inside an event handler. Server code is trusted and isn't subject to `allow` and `deny` restrictions. That includes methods that are called with `Meteor.call` — they are expected to do their own access checking rather than relying on `allow` and `deny`. You can call `allow` as many times as you like, and each call can include any combination of `insert`, `update`, and `remove` functions. The functions should return `true` if they think the operation should be allowed. Otherwise they should return `false`, or nothing at all (`undefined`). In that case Meteor will continue searching through any other `allow` rules on the collection. The available callbacks are: