{"id":27106969,"url":"https://github.com/meteor/publish-counts","last_synced_at":"2025-04-06T20:19:27.648Z","repository":{"id":13677081,"uuid":"16370796","full_name":"meteor/publish-counts","owner":"meteor","description":"Meteor package to help you publish the count of a cursor, in real time","archived":false,"fork":false,"pushed_at":"2024-03-20T14:30:24.000Z","size":98,"stargazers_count":200,"open_issues_count":16,"forks_count":48,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-06T04:51:56.340Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://atmospherejs.com/tmeasday/publish-counts","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meteor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-01-30T07:17:05.000Z","updated_at":"2025-03-31T22:26:44.000Z","dependencies_parsed_at":"2024-06-19T02:52:30.758Z","dependency_job_id":"09105779-252e-4b20-97e9-8380e06cff68","html_url":"https://github.com/meteor/publish-counts","commit_stats":null,"previous_names":["meteor/publish-counts"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Fpublish-counts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Fpublish-counts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Fpublish-counts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meteor%2Fpublish-counts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meteor","download_url":"https://codeload.github.com/meteor/publish-counts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247543757,"owners_count":20955890,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-06T20:19:27.127Z","updated_at":"2025-04-06T20:19:27.642Z","avatar_url":"https://github.com/meteor.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Publish Counts\n\nA package to help you publish the count of a cursor, in real time.\n\nPublish-counts is designed for counting a small number of documents around an\norder of 100.  Due to the real-time capability, this package should not be used\nto count all documents in large datasets.  Maybe some, but not all. Otherwise,\nyou will maximize your server's CPU usage as each client connects.\n\n## v1.x Breaking changes\n\nThis version is only compatible with [Meteor 3.0](https://github.com/meteor/meteor/blob/release-3.0/docs/generators/changelog/versions/3.0.md) and higher.\n\n## Table of Contents\n\n- [Installation](https://github.com/percolatestudio/publish-counts#installation)\n- [API](https://github.com/percolatestudio/publish-counts#api)\n  - [Counts.publish](https://github.com/percolatestudio/publish-counts#countspublish-server)\n  - [Counts.get](https://github.com/percolatestudio/publish-counts#countsget-client)\n  - [Counts.has](https://github.com/percolatestudio/publish-counts#countshas-client)\n  - [Counts.noWarnings](https://github.com/percolatestudio/publish-counts#countsnowarnings-server)\n- [Options](https://github.com/percolatestudio/publish-counts#options)\n  - [noReady](https://github.com/percolatestudio/publish-counts#noready)\n  - [nonReactive](https://github.com/percolatestudio/publish-counts#nonreactive)\n  - [countFromField](https://github.com/percolatestudio/publish-counts#countfromfield)\n  - [countFromFieldLength](https://github.com/percolatestudio/publish-counts#countfromfieldlength)\n  - [noWarnings](https://github.com/percolatestudio/publish-counts#nowarnings)\n- [Template helpers](https://github.com/percolatestudio/publish-counts#template-helpers)\n- [Notes]()\n  - [Observer handle leak testing](https://github.com/percolatestudio/publish-counts#observer-handle-leak-testing)\n  - [Why doesn't this library count directly in Mongo? or...](https://github.com/percolatestudio/publish-counts#why-doesnt-this-library-count-directly-in-mongo-or)\n  - [Scalable count packages](https://github.com/percolatestudio/publish-counts#scalable-count-packages)\n  - [Compatiblity with Meteor \u003c v1.3](https://github.com/percolatestudio/publish-counts#compatibility-with-meteor--13)\n- [Frequently Asked Questions](https://github.com/percolatestudio/publish-counts#frequently-asked-questions) \\[[Issues](https://github.com/percolatestudio/publish-counts/issues?q=label%3Afaq)]\n- [License](https://github.com/percolatestudio/publish-counts#license)\n\n## Installation\n\n``` sh\n$ meteor add tmeasday:publish-counts\n```\n\n## API\n\n### Counts.publish [server]\n\n`Counts.publish(subscription, counter-name, cursor, options)`\n\nSimply call `Counts.publish` within a publication, passing in a name and a cursor:\n\n#### Example 1\n##### JavaScript\n```js\nMeteor.publish('publication', function() {\n  Counts.publish(this, 'name-of-counter', Posts.find());\n});\n```\n\n##### Coffeescript\n```coffeescript\nMeteor.publish 'publication', -\u003e\n  Counts.publish this, 'name-of-counter', Posts.find()\n  return undefined    # otherwise coffeescript returns a Counts.publish\n                      # handle when Meteor expects a Mongo.Cursor object.\n```\n\nThe `Counts.publish` function returns the observer handle that's used to maintain the counter. You can call its `stop` method in order to stop the observer from running.\n\nWarning: Make sure you call *collection*`.find()` separately for `Counts.publish` and the `Meteor.publish` return value, otherwise you'll get empty documents on the client.\n\nFor more info regarding the `options` parameter, see [Options](#options).\n\n### Counts.get [client]\n\n`Counts.get(counter-name)`\n\nOnce you've subscribed to `'publication'` ([Ex 1](#example-1)), you can call `Counts.get('name-of-counter')` to get the value of the counter, reactively.\n\nThis function will always return an integer, `0` is returned if the counter is neither published nor subscribed to.\n\n### Counts.has [client]\n\n`Counts.has(counter-name)`\n\nReturns true if a counter is both published and subscribed to, otherwise returns false.  This function is reactive.\n\nUseful for validating the existence of counters.\n\n### Counts.noWarnings [server]\n\n`Counts.noWarnings()`\n\nThis function disables all development warnings on the server from publish-counts.\n\nNot recommended for use by development teams, as warnings are meant to inform\nlibrary users of potential conflicts, inefficiencies, etc in their use of\npublish-counts as a sanity check.  Suppressing all warnings precludes this\nsanity check for future changes.  See the [`noWarnings`](#nowarnings) option\nfor fine-grained warning suppression.\n\n## Options\n\n### noReady\n\nIf you publish a count within a publication that also returns cursor(s), you probably want to pass `{noReady: true}` as a final argument to ensure that the \"data\" publication sets the ready state. For example, the following publication sends down 10 posts, but allows us to see how many there are in total:\n\n```js\nMeteor.publish('posts-with-count', function() {\n  Counts.publish(this, 'posts', Posts.find(), { noReady: true });\n  return Posts.find({}, { limit: 10 });\n});\n```\n\n### nonReactive\n\nIf you specify `{nonReactive: true}` the cursor won't be observed and only the initial count will be sent on initially subscribing. This is useful in some cases where reactivity is not desired, and can improve performance.\n\n### countFromField\n\n`countFromField` allows you to specify a field to calculate the sum of its numbers across all documents.\nFor example if we were to store page visits as numbers on a field called `visits`:\n\n```\n{ content: 'testing', visits: 100 },\n{ content: 'a comment', visits: 50 }\n```\n\nWe could then publish them like:\n\n```js\nMeteor.publish('posts-visits-count', function() {\n  Counts.publish(this, 'posts-visits', Posts.find(), { countFromField: 'visits' });\n});\n```\n\nAnd calling `Counts.get('posts-visits')` returns `150`\n\nIf the counter field is deeply nested, e.g.:\n\n```\n{ content: 'testing', stats: { visits: 100 } },\n{ content: 'a comment', stats: { visits: 50 } }\n```\n\nThen use an accessor function instead like:\n\n```js\nMeteor.publish('posts-visits-count', function() {\n  Counts.publish(this, 'posts-visits',\n    Posts.find({}, { fields: { _id: 1, 'stats.visits': 1 }}),\n    { countFromField: function (doc) { return doc.stats.visits; } }\n  );\n});\n```\n\nNote that when using an accessor function, you must limit the fields fetched if desired, otherwise Counts will fetch entire documents as it updates the count.\n\n### countFromFieldLength\n\n`countFromFieldLength` allows you to specify a field to calculate the sum of its **length** across all documents.\nFor example if we were to store the userIds in an array on a field called `likes`:\n\n```\n{ content: 'testing', likes: ['6PNw4GQKMA8CLprZf', 'HKv4S7xQ52h6KsXQ7'] },\n{ content: 'a comment', likes: ['PSmYXrxpwg276aPf5'] }\n```\n\nWe could then publish them like:\n\n```js\nMeteor.publish('posts-likes-count', function() {\n  Counts.publish(this, 'posts-likes', Posts.find(), { countFromFieldLength: 'likes' });\n});\n```\n\nIf the counter field is deeply nested, e.g.:\n\n```\n{ content: 'testing', popularity: { likes: ['6PNw4GQKMA8CLprZf', 'HKv4S7xQ52h6KsXQ7'] } },\n{ content: 'a comment', popularity: { likes: ['PSmYXrxpwg276aPf5'] } }\n```\n\nThen use an accessor function instead like:\n\n```js\nMeteor.publish('posts-likes-count', function() {\n  Counts.publish(this, 'posts-likes',\n    Posts.find({}, { fields: { _id: 1, 'popularity.likes': 1 }}),\n    { countFromFieldLength: function (doc) { return doc.popularity.likes; } }\n  );\n});\n```\n\nNote that when using an accessor function, you must limit the fields fetched if desired, otherwise Counts will fetch entire documents as it updates the count.\n\n### noWarnings\n\nPass the option, `noWarnings: true`, to `Counts.publish` to disable its warnings in\na development environment.\n\nEach call to `Counts.publish` may print warnings to the console to inform\ndevelopers of non-fatal conflicts with publish-counts.  In some situations, a\ndeveloper may intentionally invoke `Counts.publish` in a way that generates a\nwarnings.  Use this option to disable warnings for a particular invocation of\n`Counts.publish`.\n\nThis fine-grained method of warning suppression is recommended for development\nteams that rely on warnings with respect to future changes.\n\n## Template helpers\n\nTo easily show counter values within your templates, use the `getPublishedCount` or `hasPublishedCount` template helper.\n\nExample:\n```html\n\u003cp\u003eThere are {{getPublishedCount 'posts'}} posts.\u003c/p\u003e\n\u003cp\u003e\n  {{#if hasPublishedCount 'posts'}}\n    There are {{getPublishedCount 'posts'}} posts.\n  {{else}}\n    The number of posts is loading...\n  {{/if}}\n\u003c/p\u003e\n```\n\n## Notes\n\n### Observer handle leak testing\n\nThe package includes a test that checks the number of observer handles opened and closed (to check for memory leaks). You need to run the `enable-publication-tests-0.7.0.1` branch of `percolatestudio/meteor` to run it however.\n\n### Why doesn't this library count directly in Mongo? or...\n**Why does my MongoDB connection time-out with large (1000+) datasets?**\n\nThis package is designed primarily for correctness, not performance. That's why\nit's aimed at counting smaller datasets and keeping the count instantly up to\ndate.\n\nTo achieve perfect correctness in Meteor data layer, we use a database observer\nto know immediately if a relevant change has occurred. This approach does not\nnecessarily scale to larger datasets, as the observer needs to cache the entire\nmatching dataset (amongst other reasons).\n\nCounting large datasets in this manner is suspected to cause database\nconnections to time out (see\n[#86](https://github.com/percolatestudio/publish-counts/issues/86)).\n\nAn alternative approach would be to take a .count() of the relevant cursor (or\nperform an aggregation in more complex use cases), and poll it regularly to\nupdate the count. Bulletproof Meteor provides a proof of concept of this\napproach in their [bullet-counter][proof-of-concept] example.\n\n[proof-of-concept]: https://github.com/bulletproof-meteor/bullet-counter/blob/solution/lib/server.js\n\nWe'd love to see someone publish a package for this use case! If you do end up\nmaking such a package, let us know and we'll link it here.\n\n#### Scalable Count Packages\n\n* [publish-performant-counts](https://atmospherejs.com/natestrauser/publish-performant-counts) - Performant solution derived directly from [bullet-counter](https://github.com/bulletproof-meteor/bullet-counter/tree/solution).\n* [meteor-publish-join](https://www.npmjs.com/package/meteor-publish-join) - Publish expensive-aggregated values\n\n#### Compatibility with Meteor \u003c 1.3\n\nPublish-counts 0.8.0 introduces an explicit dependency on the underscore js\nlibrary which may be incompatible with versions of Meteor below 1.3.  Please\nupgrade Meteor to the latest version or, if you cannot, continue to use\npublish-counts 0.7.3.\n\n## Frequently Asked Questions\n\nMore information can be found in the [FAQ\nSection](https://github.com/percolatestudio/publish-counts/issues?q=label%3Afaq)\nof the issue tracker.\n\n## License\n\nMIT. (c) Percolate Studio\n\npublish-counts was developed as part of the [Verso](http://versoapp.com) project.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeteor%2Fpublish-counts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeteor%2Fpublish-counts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeteor%2Fpublish-counts/lists"}