Capped collections in Meteor 1.3/1.4

Is there still capped collection in MongodB for 1.3 / 1.4?

This is quite an old article from 2013-2014

MongoDB still has these, but minimongo doesn’t have an option for creating them. However, you should be able to create them via the rawDatabase method.

Hi Rob,

Converting to rawCollections would be:

var Collections = {}

FutureTasks = Collections.FutureTasks = new Mongo.Collection('future_tasks');

var res = FutureTasks.rawCollection() ??

The rawDatabase method gives you access to the underlying npm module API’s db class, which itself gives you access to the createCollection method.

So, in order to create a new, capped collection, you need to have a pre-existing collection to get the db reference from. For example, if you’re using (non-multi-server) Meteor accounts, you could use Meteor.users as your initial collection. Then, to create a capped collection, something like this on the server:

import { Meteor } from 'meteor/meteor';

const db = Meteor.users.rawDatabase(); // get the underlying db class
const createCollection = Meteor.wrapAsync(db.createCollection, db); // wrap into futures/fibers

// now create a capped collection called bob:
try {
  createCollection('bob', { capped: true, max: 100 });
} catch(error) {
  // do something with the error
}

// All being well we can now connect to this collection with
const Bob = new Mongo.Collection('bob');
3 Likes

I tried your method but the Meteor.users is undefined in my case

Which is why I said

if you’re using (non-multi-server) Meteor accounts, you could use Meteor.users as your initial collection.

Just use a collection you do have.

BTW, I notice I missed the size parameter off:

createCollection('bob', { capped: true, max: 100, size: 200 });
1 Like

Thanks a lot. I will try it.

I forgot to mention that in my case, I’m dealing with a “C” program that creates the collections as capped collections so I can’t seem to call “createCollection” on them as I’m getting error saying that the collection already exists.

I was wondering if there is a way to access capped collections that are created by some other code and still see them as capped collections with the actual limited documents in them without client keeping growing the cached documents beyond the capped limit ending up showing more documents on the client side than what actually exists on the server.

If the collection already exists, it can probably be referenced just like any other Mongo collection (new Mongo.Collection('xxx')), but I’ve not tested this.

However, you can always use the underlying MongoDB library (which is available on Collection.rawCollection()), but you should note that minimongo does not support capped collections, so although you’ll be able to perform CRUD operations, you’ll probably not get livedata:

Thank you so much for the clarification. So if minimongo doesn’t support capped collections, then I guess I’m left with collection hooks to delete the documents in the minimongo that are not existing on the server anymore.

I’ve not tested the actual behaviour - you may find it works - let us know :slight_smile:

Just a note that this doesn’t seem to work anymore after Meteor 1.11 and the update to mongodb driver 3.6.0.

The code runs fine the very first time, when the collection doesn’t actually exist in Mongo. After that, the createCollection('bob', { capped: true, max: 100 }); line throws an exception :

MongoError: a collection 'meteor.bob' already exists
     at Connection.<anonymous> (HOME/.meteor/packages/npm-mongo/.3.8.0.1u7psm6.649z++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb/lib/core/connection/pool.js:451:61)
     at Connection.emit (events.js:315:20)
     at Connection.EventEmitter.emit (domain.js:483:12)
     at processMessage (HOME/.meteor/packages/npm-mongo/.3.8.0.1u7psm6.649z++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb/lib/core/connection/connection.js:452:10)
     at Socket.<anonymous> (HOME/.meteor/packages/npm-mongo/.3.8.0.1u7psm6.649z++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb/lib/core/connection/connection.js:621:15)
     at Socket.emit (events.js:315:20)
     at Socket.EventEmitter.emit (domain.js:483:12)
     at addChunk (_stream_readable.js:295:12)
     at readableAddChunk (_stream_readable.js:271:9)
     at Socket.Readable.push (_stream_readable.js:212:10)
     at TCP.onStreamRead (internal/stream_base_commons.js:186:23) 

I suspect it’s because of the “Changes in behavior of Db.prototype.createCollection” section in
https://github.com/mongodb/node-mongodb-native/releases/tag/v3.6.0,
but at the moment I can’t seem to be able to define and work with a capped collection in Meteor 1.11

You could use Db.listCollections() to find out whether the collection already exists, and perform the collection creation conditionally.

See Node.js MongoDB Driver API 3.6 Db.listCollections

1 Like

@peterfkruger Thanks ! checking the existence of the collection with listCollections() first does seem to work :

const db = Meteor.users.rawDatabase();
const collectionExists = db.listCollections({ name: 'bob' }).hasNext().await();
if (!collectionExists) {
  db.createCollection('bob', { capped: true, max: 100 }).await();
}
const Bob = new Mongo.Collection('bob');

This does create the (correctly capped) collection if it doesn’t exist yet, and leaves you with the usual Mongo.Collection instance to work with.

2 Likes

Gotcha! It took me a while to comprehend that the .await() is from Meteor’s Promise polyfill! Until now I was only aware of the static function Promise.await().

1 Like