0

Help! Something very strange is happening within my app.

I have a merchantReview template that is supposed to show the number of reviewers.
Below is what the template looks like:

<template name="merchantReview">
<div> {{numberOfReviewers}}&nbsp;Total</div>

And what the helper code looks like:

Template.merchantReview.helpers({

 'numberOfReviewers': function () { 

  var numberOfReviewers = 0;
  var merchantProfileId = Session.get('offerUserId2');
  console.log("The numberOfReviews _id session is: " + merchantProfileId );

    merchantReviews.find({_id: merchantProfileId}).map(function (doc)
      {
        numberOfReviewers += doc.noOfReviewers;
      });

    return numberOfReviewers;
    }
});

This yields nothing on the merchantReview page at all.

Lets have a look at the Router:

Router.route('/merchantReview/:_id', {
template: 'merchantReview',
data: function(){
    },

waitOn: function(){

  return Meteor.subscribe('merchantReviews');
  }  
});

And what am subscribing to:

Meteor.publish('merchantReviews', function publishmerchantReviews(){
return merchantReviews.find();
});

Now for the "Something very strange" part. When I run this following code (which is similar to the helper code) in the chrome browser console, I get mixed results.

When I run the below:

  var numberOfReviewers = 0;
  var merchantProfileId = Session.get('offerUserId2');
  console.log("The _id is: " + merchantProfileId );

merchantReviews.find({_id: merchantProfileId}).map(function (doc)
  {
    numberOfReviewers += doc.noOfReviewers;
  });

console.log (numberOfReviewers);

...it yields:

The _id is: udEnfEmy5DSBvDsSy
0

As you see, it bypasses the merchantReviews.find query.

However when slightly alter the code, and run:

  var numberOfReviewers = 0;
  var merchantProfileId = Session.get('offerUserId2');
  console.log("The _id is: " + merchantProfileId );

merchantReviews.find({_id: "udEnfEmy5DSBvDsSy"}).map(function (doc)
  {
    numberOfReviewers += doc.noOfReviewers;
  });

console.log (numberOfReviewers);

This time it yields:

The _id is: udEnfEmy5DSBvDsSy
93

Strange isn't it?

Can anyone explain why the merchantReviews.find({_id: merchantProfileId})... query doesn't recognize the merchantProfileId variable which holds the udEnfEmy5DSBvDsSy value? And how do I fix this?

SirBT
  • 1,580
  • 5
  • 22
  • 51
  • Can you add `console.log('"' + merchantProfileId + '"')`? It's possible you have an extra space on the end. – user3374348 May 12 '17 at 11:01
  • @user3374348 I followed your advise and the result is: "udEnfEmy5DSBvDsSy" confirming that there isn't any extra space on any end. – SirBT May 12 '17 at 11:13
  • Where do you set the `Session` var? – user3374348 May 12 '17 at 11:19
  • Your experiment does not indicate bypassing the query, it simply indicates the result was 0. There are other things which may cause this. Is it possible that the publication was not ready when you ran the first version of the code? If you want to debug things more efficiently, you need to isolate things better. For example, log data as close to the root as possible (the result of a query instead of a calculation done based on it would give a better indication of how the query was executed). – MasterAM May 12 '17 at 15:18
  • @user3374348 The Session var is set on the previous page triggered by a onclick event before `Router.go('/merchantReview');` What is strange is that in the helper, the Session.get is read. proof being the `The _id is: udEnfEmy5DSBvDsSy` however the variable isn't applied in the query. – SirBT May 15 '17 at 08:32
  • What happends if you compare your Session var with the working id with `merchantProfileId === 'udEnfEmy5DSBvDsSy'` does it return true? – Jankapunkt May 15 '17 at 10:34
  • @Jankapunkt This is what happens, when I run this in the chrome browser console: ` var merchantProfileId = Session.get('offerUserId2'); if (merchantProfileId === "udEnfEmy5DSBvDsSy") { alert("Yo merchantProfileId === 'udEnfEmy5DSBvDsSy' "); } console.log("The _id session is: " + merchantProfileId ); merchantReviews.find({_id: merchantProfileId}).count();` yields: `The _id session is: udEnfEmy5DSBvDsSy 0` No alert pops up :-(. Any idea whats going on here? – SirBT May 15 '17 at 13:01
  • 1
    if no alert pops up it seems very likely, that your merchantProfileId has somewhere a hidden whitespace included. Please do two things: first `console.log(merchantProfileId.length, String("udEnfEmy5DSBvDsSy").length)` and second what happens if you do `merchantProfileId = merchantProfileId.replace(/\s+/g)` ? – Jankapunkt May 15 '17 at 13:04

3 Answers3

0

You can simplify and speed up your helper by just using .count() on the cursor. If, as you mentioned in the comments, your offerUserId2 session variable returns an array then you can just reference its first element with [0]:

Template.merchantReview.helpers({
 numberOfReviewers() { 
   return merchantReviews.find(Session.get('offerUserId2')[0]).count();
 }
})
Michel Floyd
  • 18,793
  • 4
  • 24
  • 39
  • Great coding advise, though it doesn't make a difference when I runt this in the chrome browser console. The query still yields "0" when it should yield 1. Whats strange about this issue, is that to get the desired/correct query results, I have to insert the actual `_id number` instead of the variable when I run the code similar to this: `Template.merchantReview.helpers({ numberOfReviewers() { return merchantReviews.find(_id: "udEnfEmy5DSBvDsSy").count(); } })` – SirBT May 15 '17 at 08:32
  • 1
    Then `Session.get('offerUserId2')` doesn't contain what you think it contains. Try `if (Session.get('offerUserId2') === "udEnfEmy5DSBvDsSy") console.log("offerUserId2 is what I expect!")` – Michel Floyd May 15 '17 at 17:45
  • You are very right. I added the `if (Session.get('offerUserId2') === "udEnfEmy5DSBvDsSy")` and this failed. It turns out that the `Session.get('offerUserId2')` is actually in array form. I did manage to resolve the issue by sanitizing the variable using the toString() function. – SirBT May 16 '17 at 08:07
0

The reason why the variable wasn't being recognized in the query is because the variable was in array form instead of string form.

I realized this by console.log("The _id is: " + merchantProfileId );

This would sometimes yield:

["udEnfEmy5DSBvDsSy"]

I resolved his by sanitizing the variable to ensure its a string not an array using the toString() function. So in code its : merchantProfileId.toString();

Following is the full resolution in code:

var numberOfReviewers = 0;
var merchantProfileId = Session.get('offerUserId2');

// Below immediately sanitize the variable ensuring it is a string
// before its used in the query.
merchantProfileId = merchantProfileId.toString();

console.log("The _id is: " + merchantProfileId );

merchantReviews.find({_id: merchantProfileId}).map(function (doc)
{
  numberOfReviewers += doc.noOfReviewers;
});

console.log (numberOfReviewers);

This yields:

The _id is: udEnfEmy5DSBvDsSy
104
SirBT
  • 1,580
  • 5
  • 22
  • 51
-2

Your problem is a classic javascript async gotcha. Looking at your code,

merchantReviews.find({_id: "udEnfEmy5DSBvDsSy"}).map(function (doc)
  {
    numberOfReviewers += doc.noOfReviewers;
  });

console.log (numberOfReviewers);

The adding to numberOfReviewers happens in the callback for merchantReviews.find() - which usually happens at some later time. Your console.log likely happens before that, which explains why you get wierd results. If you change your code to this, you will get consistent results.

merchantReviews.find({_id: "udEnfEmy5DSBvDsSy"}).map(function (doc)
  {
    numberOfReviewers += doc.noOfReviewers;
    console.log (numberOfReviewers);
  });

Think of it this way, in javascript time moves to the right, not down the page. So indented code that is part of a callback (and indented to the right) happens after the code at the bottom.

Mikkel
  • 7,693
  • 3
  • 17
  • 31
  • 1
    `.find(...).map(...)` is synchronous in Meteor. – user3374348 May 12 '17 at 12:13
  • @Mikkel Perhaps I wasn't clear enough, but the issue here and, the strange thing about my issue is that when I run the query using the variable `merchantProfileId` instead of the actual value itself being: `"udEnfEmy5DSBvDsSy"` for instance: `merchantReviews.find({_id: merchantProfileId}).map(function (doc) { numberOfReviewers += doc.noOfReviewers; console.log (numberOfReviewers); });` I get a undesirable/wrong result, however when I replace the variable with the actual variable value such as in: – SirBT May 15 '17 at 08:34
  • @Mikkel ...`merchantReviews.find({_id: "udEnfEmy5DSBvDsSy"}).map(function (doc) { numberOfReviewers += doc.noOfReviewers; console.log (numberOfReviewers); });` I get a correct result. I need to understand why the query isnt recognizing my variable values. Why is this happening? I did follow your advise, off course using the variable instead of the actual value itself but sadly got the same undesirable/wrong query result. :-( – SirBT May 15 '17 at 08:34