(SOLVED) Custom non-reactive publication



In eshop we have Product view and in mongo product document we have property - array of accessories _id’s.
I need to call subscribe with argument ( our main product _id) and get back max 3 documents from each category :smiley: Cause we are not going to show more in this view.

For now I am thinking about this approach:
findOne that main product _id, get accessoriesList from it
Products.find where _id is in accessoriesList
Than want to transform results by aggregate
And than publish them using publish low level API to custom clientside collection.

Am I thinking in the right direction?


As usual, standard pipeline aggregation could not solve it easily as it does not support $limit per key
So I added mapReduce to meteorhacks:meteor-aggregate package and submitted PR for review https://github.com/ShockiTV/meteor-aggregate
And now back to working directly on our eshop project.


Sooo, end result
warning: coffeescript :smiley:
I have custom client side collection to hold results

@Accessories = new Mongo.Collection('accessories')

Subscribing to it from template

Template.productAccessories.onCreated ->
  @contentSub = @subscribe "productAccessories", @data._id

And that ugly publication with mapReduce

Meteor.publish 'productAccessories', (productId) ->
  currentProduct = MasterProducts.findOne({
    _id: productId
      accessories: 1

  if not currentProduct?

  accessoriesList = currentProduct.accessories

  if accessoriesList.length is 0

  mapFunction1 = () ->
      _id: @_id
      product: @product

  reduceFunction1 = (keyGroup, valuesItems) ->
    if valuesItems.length > 3
      return {results: valuesItems[0...3]}
      return {results: valuesItems}

  finalizeFunction = (key, value) ->
    # return array even in case of single string value
    # cause single value is not passed to reduce function
    if value.results?
      return value.results
      return [ value ]

  reduceResult = MasterProducts.mapReduce(
        inline: 1
          $in: accessoriesList
      finalize: finalizeFunction

  @added("accessories", 'test', reduceResult)