What's wrong with my Meteor publication?

117 views Asked by At

I have a publication, essentially what's below:

Meteor.publish('entity-filings', function publishFunction(cik, queryArray, limit) {

  if (!cik || !filingsArray)
    console.error('PUBLICATION PROBLEM');

  var limit = 40;


  var entityFilingsSelector = {};
  if (filingsArray.indexOf('all-entity-filings') > -1)
    entityFilingsSelector = {ct: 'filing',cik: cik};
  else
    entityFilingsSelector = {ct:'filing', cik: cik, formNumber: { $in: filingsArray} };


  return SB.Content.find(entityFilingsSelector, {
    limit: limit
  });


});

I'm having trouble with the filingsArray part. filingsArray is an array of regexes for the Mongo $in query. I can hardcode filingsArray in the publication as [/8-K/], and that returns the correct results. But I can't get the query to work properly when I pass the array from the router. See the debugged contents of the array in the image below. The second and third images are the client/server debug contents indicating same content on both client and server, and also identical to when I hardcode the array in the query.

My question is: what am I missing? Why won't my query work, or what are some likely reasons it isn't working?

enter image description here enter image description here enter image description here

2

There are 2 answers

0
user3374348 On BEST ANSWER

In that first screenshot, that's a string that looks like a regex literal, not an actual RegExp object. So {$in: ["/8-K/"]} will only match literally "/8-K/", which is not the same as {$in: [/8-K/]}.

Regexes are not EJSON-able objects, so you won't be able to send them over the wire as publish function arguments or method arguments or method return values. I'd recommend sending a string, then inside the publish function, use new RegExp(...) to construct a regex object.

If you're comfortable adding new methods on the RegExp prototype, you could try making RegExp an EJSON-able type, by putting this in your server and client code:

RegExp.prototype.toJSONValue = function () {
  return this.source;
};

RegExp.prototype.typeName = function () {
  return "regex";
}

EJSON.addType("regex", function (str) {
  return new RegExp(str);
});

After doing this, you should be able to use regexes as publish function arguments, method arguments and method return values. See this meteorpad.

3
Seth Malaki On

/8-K/.. that's a weird regex. Try /8\-K/.

A minus (-) sign is a range indicator and usually used inside square brackets. The reason why it's weird because how could you even calculate a range between 8 and K? If you do not escape that, it probably wouldn't be used to match anything (thus your query would not work). Sometimes, it does work though. Better safe than never.

/8\-K/ matches the string "8-K" anywhere once.. which I assume you are trying to do.

Also it would help if you would ensure your publication would always return something.. here's a good area where you could fail:

if (!cik || !filingsArray)
    console.error('PUBLICATION PROBLEM');

If those parameters aren't filled, console.log is probably not the best way to handle it. A better way:

if (!cik || !filingsArray) {
     throw "entity-filings: Publication problem.";
     return false; 
} else {
  // .. the rest of your publication
} 

This makes sure that the client does not wait unnecessarily long for publications statuses as you have successfully ensured that in any (input) case you returned either false or a Cursor and nothing in between (like surprise undefineds, unfilled Cursors, other garbage data.