0

I am implementing a like feature, the user can like and unlike a thread.

The thread model is like this:

const ThreadSchema = new mongoose.Schema({
    author: {
        id: { type: ObjectID, required: true, ref: 'User' },
        screen_name: { type: String, required: true },
        picture: { type: String, required: true },
    },
    theme: { type: String },
    text: { type: String, required: true },
    comments: {
        count: { type: Number, default: 0 },
    },
    likes: {
        count: { type: Number, default: 0 },
        users: [{
            _id: false,
            id: { type: ObjectID, required: true, ref: 'User' },
            screen_name: { type: String, required: true },
            picture: { type: String, required: true },
        }],
    },
}, {
    timestamps: true,
});

Something tricky is that when the user sends the request to get the thread information, I need to tell the client whether this user has liked this thread before or not.

Does that mean that every time when the client sends a request to get the thread, I need to loop through thread.likes.users to find whether his ID is there? This check seems pretty heavy especially when the user tries to retrieve a list...

Any better solution for this?

The requirement is simple, just before the user even clicks the like button, the state should already there to indicate if this thread has been liked by this user or not.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Albert Gao
  • 3,653
  • 6
  • 40
  • 69
  • Expanding/Summarizing on the [detail in the linked answer](https://stackoverflow.com/questions/28006521/how-to-model-a-likes-voting-system-with-mongodb), from a "client" perspective you only really "need" know if the "current user" has already liked the "thread". So you simply project the matched item from the array with a GET. `Thread.findOne({ "_id": threadId }, { "likes.users": { "$elemMatch": { "$eq": userId } })` and the rest of the projection. But that is actually expanded on in that answer. – Neil Lunn Jun 14 '17 at 10:34
  • @NeilLunn Still thanks, read that answer, helperful, but the elemMatch in mongoose is a little bit confuse, you save my day! – Albert Gao Jun 14 '17 at 10:46
  • Sorry my bad. The `$elemMatch` side would rather be like `{ "likes.users": { "$elemMatch": { "id": ObjectId('593a9ea21736ec9b1a9e909b') } } }`. The example in the answer was using `$eq` because the array was only comprised of `ObjecId` values, as opposed to your structure which has sub-documents with an `id` property. There is a link to the documentation in the question as well. – Neil Lunn Jun 14 '17 at 11:24
  • I'm rolling back your edits. Please [Ask a new Question](https://stackoverflow.com/questions/ask) instead since you are changing the question from what you originally asked. – Neil Lunn Jun 14 '17 at 11:34
  • @NeilLunn Sorry, no problem now, I use `.elemMatch( 'likes.users', { 'id': '593a9ea21736ec9b1a9e909d' })` , works now. – Albert Gao Jun 14 '17 at 11:41
  • Here, you [**Ask a new Question**](https://stackoverflow.com/questions/ask). This is not a threaded discussion. One question, One answer ( or a couple of answers sometimes ). You asked one question here and were told it already has an answer. Your "trying to adapt that answer to your code" is a **New Question**. Please click on the link and do so. – Neil Lunn Jun 14 '17 at 11:44

0 Answers0