Display array value in template


#1

Hello

Let’s say I have the following collection:

collection

{
  "_id": "ybkMQKN9jTBxARnML",
  "userId": "hFefx7scAPgcQFoDg",
  "cards": [
    {
      "brand": "hFefx7scAPgcQFoDg",
      "points": 9
    },
    {
      "brand": "vxLGSeqnBEh2xQ2TY",
      "points": 5
    }
  ]
}

I would like to display the value “5” in a Meteor template.

I have tried :

collection.find({userId:“hFefx7scAPgcQFoDg”,“cards.brand”:“vxLGSeqnBEh2xQ2TY”},{‘cards.$’: 1})

or

collection.find({userId:"hFefx7scAPgcQFoDg","cards.brand":"vxLGSeqnBEh2xQ2TY"},{_id: 0, cards: {$elemMatch: {brand: "vxLGSeqnBEh2xQ2TY"}}})

But it returns the whole array. Could you please give me a hint?

Thanks

Michael


#2

Using a combination of .fetch() and dot notation should be able to get you the value you are looking for.

Collection.find({yoursearchparams}).fetch().cards.points

Of course, if you are getting multiple hits, you can use:

Collection.find({yoursearchparams}).fetch()[x].cards.points, where x is an object in your fetched array.

Or, if you know you are only going to get one unique hit, you can use findOne(), which is like doing a find and fetch()[0].

Hope this helps!


#3

Thanks for putting me on the way.

if I do:

collection.find({userId : "9TRiKinK2QJfDE8Ab" , "cards.brand" : "cu7dN8yDK8Sx58isN" }).fetch().cards.points

It doesn’t work, points is undefined (even though this record exists) but

   collection.findOne({userId : "9TRiKinK2QJfDE8Ab" , "cards.brand" : "cu7dN8yDK8Sx58isN" }).cards[0].points

works. The problem is that is returns the whole array, and I don’t know in advance which index I need to display ( [x] ). How do I return the array element which matches “cards.brand” : “cu7dN8yDK8Sx58isN” ?

Thank you


#4

trying 10 different ways, with $, with elemMatch… I also get the full array…

collection.find(
  
    { cards: {
        $elemMatch: {
            brand: "cu7dN8yDK8Sx58isN" 
            
        }
    }},

   
    { "cards.$": 1 }
).fetch()

Why is it so?


#5

this should return just one array element in the result…if not, check you may have multiple brands with the same value.

find({userId : “hFefx7scAPgcQFoDg” , “cards.brand” : “hFefx7scAPgcQFoDg” },{“cards.$”:1})


#6

It returns an object including an array of 2 again… These 2 have the different values for brand.


#7


#8

Is this what you’re trying to do?

Template.foo.helpers({
    getBrandValue: function (brand_id) {
        var user = Meteor.userId();
        return Collection.findOne({ userId: user }).cards.filter(function (card) {
            return card.brand === brand_id;
        })[0].points;
    }
});

<template name="foo">
    {{getBrandValue 'vxLGSeqnBEh2xQ2TY'}}
</template>

edit: forgot ‘points’


#9

Yes hellstad, thanks. Your solution returns

Object {brand: "cu7dN8yDK8Sx58isN", points: 4}

Then it is just to extract the points. So this does the job.

For my understanding, what is the difference between this approach and what the others propose above?

honmeteo and vigorwebsolutions, I’m trying to reproduce on another machine, here is what I get:


#10

Once you do Collection.findOne(), it just returns a regular Javascript object, so you should treat it like one. Let Mongo take care of the data fetching.


#11

I didn’t realize you were doing it on the client side, my solution works only on the server side.

Minimongo (client side storage )doesn’t support $ operator.
So it ignores array filter in your query.

If supported, this would work on the clientside too!
testq.find({userId : “hFefx7scAPgcQFoDg” , “cards.brand” : “hFefx7scAPgcQFoDg” },{fields:{“cards.$”:1}}).fetch();


#12

Thanks, I learnt something useful today.

Though, I find it weird that there is no simple command to get an array’s item.


#13

It’s rather easy to display a nested array in a template (just use #each). But it does take a little more work to isolate something in a nested array. In some cases it’s a lot nicer to store only arrays of _id Strings (as references) inside documents, instead of arrays of objects. Then store the contents in another collection. It depends on the use case though.


#14

Yes I thought about that, but aren’t documents expensive? (In case you have a huge number of users)