Why do count only return : 1?

#1

Why do count only return : 1 ?

{{countwaitingapproval}} returns 1 but I have more in the mongodb

countwaitingapproval() {
      // let userId = Meteor.userId();
      // return Friends.find({ _id: userId },{ friends: { $elemMatch: { status: 1 } } }).count();

      return Friends.find({ _id: Meteor.userId(), "friends.status": 1 }).count()
#2

The problem is the query is on the _id field.

By default, the _id field is unique - so your query could only return one document.

1 Like
#3

I have to fint amount of status 1 friends:

{
    "_id" : "8YBhc3AeKbfHaoNJ9",
    "friends" : [ 
        {
            "id1" : "Nt4ZTwqAqKfNo3avi",
            "id2" : "8YBhc3AeKbfHaoNJ9",
            "status" : 1
        }, 
        {
            "id1" : "sQEAn5HiCtEnWXHPs",
            "id2" : "8YBhc3AeKbfHaoNJ9",
            "status" : 1
        }
    ]
}
#4

You would need to remodel your data first. In this case, it would look something like this:

{
    "_id" : "8YBhc3AeKbfHaoNJ9",
    "documentOwner" : "8YBhc3AeKbfHaoNJ9",
    "friends" : [ 
        {
            "id1" : "Nt4ZTwqAqKfNo3avi",
            "status" : 1
        }, 
        {
            "id1" : "sQEAn5HiCtEnWXHPs",
            "status" : 1
        }
    ]
}

And then you would query the friends field.

#5

Once you made your query on the collection you get an object (a Document we call this), then you have to loop over your friends Array to count what you want.

By the way, as @msavin told you, your query only returns 1 Document due to the filter on the field _id, so you could use the method .findOne() (which directly returns an Object), instead of .find() (which returns a Cursor) followed by .fetch() to get an Array of the results.

1 Like
#6

What is the problem with;

 "id2" : "8YBhc3AeKbfHaoNJ9",

_id is the userid (documentowner)

#7

I think you want to count the elements in the friends-array and not the documents. But with Friends…count() you can only count the documents of the collection Friends. Instead you need to get the document where there is at least one friends-item with status 1 and then filter the array (not the collection) and return its length.

 const friend = Friends.findOne({ _id: Meteor.userId(), "friends.status": 1 }, {fields: {friends: 1}});
 return friend.friends.filter(f => f.status === 1).length;
#8
    created() {

      const friend = Friends.findOne({ _id: Meteor.userId(), "friends.status": 1 }, {fields: {friends: 1}});
      this.countwaitingapproval = friend.friends.filter(f => f.status === 1).length;

I get this

[Vue warn]: Property or method “countwaitingapproval” is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

#9

I can’t help you with vue.

What does console.log(friend.friends.filter(f => f.status === 1).length); print?

#10

find() actually returns a cursor, u need to use fetch() to get the results array

#11

It almost works with:

return Friends.find({"_id": Meteor.userId()},{friends: {$elemMatch: {status:0}}}).fetch()[0].friends.length

but if the profile dont have any friends in the friends collections then it will come with this bug:

[Vue warn]: Error in render: "TypeError: Cannot read property 'friends' of undefined"

found in

---> <AppLayout>

#12

Then you need to handle that case appropriately or think about remodelling your schema

#13

is there no way to handle the “friends”

I have tried friends:[]

#14

Just handle the case where it’s undefined:

Instead of

return Friends.find({"_id": Meteor.userId()},{friends: {$elemMatch: {status:0}}}).fetch()[0].friends.length

use something like:

const friendDoc = Friends.find({"_id": Meteor.userId()},{friends: {$elemMatch: {status:0}}}).fetch()[0]
return (friendDoc && friendDoc.friends && friendDoc.friends.length) || 0;

Which which check that the next part of the nested object exists before trying to access a property on it, and falling back to 0 if there are no friends.

Which is what I meant by "handle that case appropriately"
Of course, if you modelled your data properly this wouldn’t be so painful

#15

So are you trying to create friends and friend requests?

#16

Actually, an easier way to deal with friends management would be to check out the socialize: family of packages, ie:

https://atmospherejs.com/socialize/friendships

1 Like
#17

thanks it worked perfect.

#18

yes I’m making two social apps with meteor, vue and vuetify

#19

I was just going to suggest my socialize packages as @coagmano did… I think you would find them to be very useful if you are building social features into an app, and especially if you are doing so in more than 1.

1 Like
#20

Also if you want an example of the packages in use you can check out the demo I am building at https://github.com/copleykj/meteor-socialize-demo. It is still a work in progress, but it demonstrates how to use the packages as well as their plug and play redis-oplog integration.

1 Like