katzkode katzkode - 17 days ago 8
Node.js Question

Why Does Looping Through a Mongoose Object Display Metadata?

Why does looping through a mongoose object with nunjucks display metadata?

I am using mongodb and nunjucks in an app I am writing.

I am trying to iterate through a model called

persona
, but doing so displays mongoose metadata associated with the record.

If I simply display the
persona
variable by writing
{{persona}}
.

My output is as follows. Just the keys/values defined in my schema.

{ _id: 582f186df1f05603132090d5, name: 'Alex', name_lower: 'alex', __v: 0,
meta: { validated: null, contributors: 'Research Team', sources: '4 Interviews' },
pain_points: { points: 'Debugging' },
ideal_day: { responsibilities: 'Coding websites.', goals: 'Finish the research site.', joys: 'Good code, Good food.', hobbies: 'Dance, Hiking, Eating' },
environment: { workspace: 'Desk', tools: 'Atom, Sketch', info_from: null, info_to: null, coworkers_relationship: null, technology_relationship: null },
basic_info: { jobtitle: 'FED', experience: '2', education: 'CS', company: '' } }


However, if I loop through the
persona




{% for name, item in persona %}
{{ name }} : {{ item }}
{% endfor %}



In addition to displaying the keys in my schema, all mongoose metadata associated with the record will also be displayed. I would like to understand why different information is displayed when I am looping over the object.



$__
isNew
errors
_doc
$__original_save
save
_pres
_posts
$__original_validate
validate
$__original_remove
remove
db
discriminators
__v
id
_id
meta
pain_points
ideal_day
environment
basic_info
updated_at
created_at
name_lower
name
schema
collection
$__handleSave
$__save
$__delta
$__version
increment
$__where



I was able to fix this problem by using Mongoose's
lean()
, but still don't understand why I experienced this behavior.

Answer

When you call {{persona}} then result is persona.toString().
If object doesn't have override method toString then result will be [Object object] (by default toString method).

When you use loop {% for key, value in persona %} then it's equals to

for(var key in obj)
  print(key + ' - ' + obj[key]);

This code prints all object properties and methods.

To exclude methods you must use next loop

for(var key in obj)
  if (typeof(obj) != 'function') // or obj.hasOwnProperty(key)
      print(key + ' ' + obj[key]);

So, to avoid your problem you must "clear" data before pass it to nunjucks or before output.
You can do it define custom filter

var env = nunjucks.configure(...

env.addFilter('lean', function(obj) {
    var res = {};
    for(var key in obj)
        if (typeof(obj) != 'function') // or obj.hasOwnProperty(key)
           res[key] = obj[key];
    return res;
});
...
{% for key, value in persona | lean %}
{{key}} - {{value}}
{% endfor %}