Mongo sort result set

private findChats(senderId: string): Promise<Mongo.Cursor<Chat>> {
    let promise: Promise<Mongo.Cursor<Chat>> = new Promise<Mongo.Cursor<Chat>>(resolve => {
      this.subscribe('chats', this.senderId, () => {
        const chats: Mongo.Cursor<Chat> = Chats.find(
          { memberIds: this.senderId },
          {
            sort: { lastMessageCreatedAt: -1 },
            transform: this.transformChat.bind(this),
            fields: { memberIds: 1, lastMessageCreatedAt: 1 } // ********
          }
        );
        resolve(chats);
      });
    });
    return promise;
  }

EDIT: Maybe not there - that’s your client code. It should be given in your publication.

1 Like

I don’t have fileds in the publications.ts.

    find: () => {
        return Chats.find(
            { memberIds: senderId },
            { sort: { lastMessageCreatedAt: -1 } }
        );
    },

Do you know where I should add it?

    find: () => {
        return Chats.find(
            { memberIds: senderId },
            { sort: { lastMessageCreatedAt: -1 } }//,
            //{ fields: { memberIds: 1, lastMessageCreatedAt: 1 } } <=== causes an error 
        );
    },

error:

[ts] Supplied parameters do not match any signature of call target.
(property) memberIds: number

Yeah - I just noticed that. In which case it will return all fields to the client. Still, it may be useful to add it to the client’s fields and re-paste the resulting documents over here, so we can clearly see the dates.

I have added it to the client (chats.ts), but it still prints the same:

    const chats: Mongo.Cursor<Chat> = Chats.find(
      { memberIds: this.senderId },
      {
        sort: { lastMessageCreatedAt: -1 },
        transform: this.transformChat.bind(this),
        fields: { memberIds: 1, lastMessageCreatedAt: 1 } 
      }
    );

and I get:

  {
    "_id": "e6ZMmRaJLPptF63z8",
    "memberIds": [
      "P9",
      "J66"
    ]
  },
  {
    "_id": "uMSJjHheTp7RhGdH3",
    "memberIds": [
      "P9",
      "J65"
    ]
  },
  {
    "_id": "CHb8FSuGSfZMPhkrW",
    "memberIds": [
      "P9",
      "J64"
    ]
  }
]

Brain’s fried and I’m losing track of what goes where. Do you have a repo I can clone?

I really appreciate your help. No pressure to get it done fast. I will send you a link soon…

You won’t be able to run the app though, because I also have a java RESTful server running for it, but I will show you the code. Hope that’s okay

1 Like

Here is my code:

If you look for models.d.ts, chats.ts and publications.ts, they are the relevant files.

So a (very) quick scan shows that you’re using the collection transform to set up lastMessageCreatedAt. Unfortunately, transform results are not available at the cursor level, which explains why the sort isn’t working.

This is the important bit of the doc referring to the transform function:

An optional transformation function. Documents will be passed through this function before being returned from fetch or findOne, and before being passed to callbacks of observe, map, forEach, allow, and deny. Transforms are not applied for the callbacks of observeChanges or to cursors returned from publish functions.

2 Likes

Thanks for that.

Do I need to set the lastMessageCreatedAt on the chat, and then save the chat? Or will it update it without saving it automatically?

Apologies, I have never used Mongo or Meteor before this.

It’s either got to be in the database, so it’s available on the cursor, or (for small result sets) you could use cursor.fetch().sort(doc => { someSortFunction} ) and work on the resulting array of docs (which will have transform fields).

1 Like

Thank you Rob.

I got it working. If I set lastMessageCreatedAt at another place, and not in the transform, it works. So the sort option was working all along, I just had not set the value.

Thanks for helping me.

1 Like