Group Query result by owned NFTs

hi where can I find in the documentation to group the query result to get the total number of owned NFT of a user from SoldItems table? Still following Cloning Rarible

you want to get the number of columns from a table for every user id?
in order to do some global statistic, or you want that data for a specific user?

did you look at this tutorial: https://www.youtube.com/watch?v=rd0TTLjQLy4&ab_channel=MoralisWeb3? it makes some statistics like this:

Moralis.Cloud.define("top_loosers", async function(request){
  	const query = new Parse.Query("betss");
    query.equalTo("win", 0);
    const pipeline = [
      {
        group:{
          objectId: "$user",
          total_sum: { "$sum": { "$toInt" : "$bet"} }
        }
         
      },
      {sort: {"total_sum": -1}},
      {limit: 10}
      ]
    const result = await query.aggregate(pipeline, {useMasterKey: true});
    return result;
});

I want to display something like this.

Where I get the count for all the NFTs owned by users. They are called biggest spender that’s why I want to do it in SoldItems table. Thanks @cryptokid ! i will try to watch that tutorial as well.

This may be what you want:

Moralis.Cloud.define("top_coins", async function(request){
    const query = new Parse.Query("Coin");
    const pipeline = [
      {
        group:{
          objectId: "$name",
          count: { "$sum": 1 }
        }
         
      },
      {sort: {"total_sum": -1}},
      {limit: 6}
      ]
    const result = await query.aggregate(pipeline, {useMasterKey: true});
    return result;
});  

will try it now, thanks! may i know what is the purpose of the limit: 6 in this code?

Thank you! really appreciate all the help

that 6 is because I saw only 6 top owners in your print screen and I thought that you only want top 6 of them

1 Like

thank you so much! @cryptokid

Works fine, but how do i get the user attributes (username and avatar)

Screen Shot 2021-10-15 at 8.30.18 PM

this is the whole cloud function. I tried doing query.select(“user.username”,“user.avatar”, “nft”);

Moralis.Cloud.define("getTopBuyer", async function(request){
    const query = new Parse.Query("SoldItems");
  	query.select("user", "nft");
    const pipeline = [
      {
        group:{
          objectId: "$user",
          count: { "$sum": 1 }
        }
         
      },
      {sort: {"total_sum": -1}},
      {limit: 6}
      ]
    const result = await query.aggregate(pipeline, {useMasterKey: true});
    return result;
});

you can try

query.select("user", "user.username", "user.avatar", "nft");
query.include("user");

I tried

Moralis.Cloud.define("getTopBuyer", async function(request){
    const query = new Parse.Query("SoldItems");
    query.select("user", "user.username", "user.avatar", "nft");
    query.include("user");
   	const queryResult = await query.find({useMasterKey:true});
    const pipeline = [
      {
        group:{
          objectId: "$user",
          username: queryResult.attributes.user.attributes.username,
          count: { "$sum": 1 }
        }
         
      },
      {sort: {"total_sum": -1}},
      {limit: 6}
      ]
    const result = await query.aggregate(pipeline, {useMasterKey: true});
    return result;
});  

and it gave me this

i tried in is “$user.username” , user.username"

group:{
          objectId: "$user",
          username: <here>,
          count: { "$sum": 1 }
}

but still no luck

You can still get the user info by making another query starting with his userid

in the same cloud function?

Yes, you can do multiple queries in the same cloud function, in this case you could do one more to get the extra info with a list of user object ids.

something like this?

Moralis.Cloud.define("getTopBuyer", async function(request){
    const query = new Parse.Query("SoldItems");
    query.select("user", "user.username", "user.avatar", "nft");
    query.include("user");
   
    const pipeline = [
      {
        group:{
          objectId: "$user",
          count: { "$sum": 1 }
        }
         
      },
      {sort: {"total_sum": -1}},
      {limit: 6}
      ]
    
    const queryResult = await query.find({useMasterKey:true});
    if (!queryResult) return;
	return{
    	"sellerUsername" : queryResult.attributes.user.attributes.username,
        "sellerAvatar" : queryResult.attributes.user.attributes.avatar,
    };

    const result = await query.aggregate(pipeline, {useMasterKey: true});
    return result;
});

No I mean something like you finish the first query:
result = await query.aggregate(pipeline, {useMasterKey: true});
and then you make another query in User table with the user IDs that you have from this result in order to get the extra information for those users.

I tried this, but it is returning [[Prototype]] : Object

oralis.Cloud.define("getTopBuyer", async function(request){
    const query = new Parse.Query("SoldItems");
    query.select("user", "user.username", "user.avatar", "nft");
    query.include("user");
   
    const pipeline = [
      {
        group:{
          objectId: "$user",
          count: { "$sum": 1 }
        }
         
      },
      {sort: {"total_sum": -1}},
      {limit: 6}
      ]
    const queryResults = await query.aggregate(pipeline, {useMasterKey: true});
    const results = [];
    for (let i = 0; i < queryResults.length; ++i) {
      const userQuery = new Moralis.Query("User");
      userQuery.select("username","avatar");
      userQuery.equalTo("username", queryResults[i].objectId );
      
  	  const usernameQuery = await userQuery.find();
      
        results.push({
            "uid" : queryResults[i].objectId,
         	"count" : queryResults[i].count,
          	"username" : usernameQuery.username,
        });
      }
  return results;

});  

You need to use userQuery.find.find({useMasterKey: true})
And you may need to change this line: userQuery.equalTo("username", queryResults[i].objectId ); as username is not the same thing as objectId