Performance Improvement - Ruby on Rails

Asked

Viewed 123 times

1

I have 3 tables:

[users] 1 ------------- n [valuations] n -------- 1 [items]

Where evaluation can be positive(evaluation: true) or negative(assessment: false), i need a method that returns all the items that the user liked and did not like... For this I made the following method in the user’s model:

# Retorna o numero de Likes
def likes
  itens = Array.new
  self.avaliacoes.where( avaliacao: true ).includes(:item).each do |avaliacao|
    itens << avaliacao.item
  end
  return itens
end

The same principle was adopted for the method for the method dislike

The idea is to do this with many users, the problem is that it is taking considerably to return the data. There is some way to improve the performance of that chunk of code? Any structure that I can keep on the server, because this query runs many times more than once per user...

  • Have you ever thought of using has many through? So you could do @usuario.itens directly, without needing the .each. Behold

  • 1

    Checks if the table evaluations has index for user_id and another for item_id.

  • @Andrey, I already have has many through but I still need to check if the evaluation was positive or negative. It has how to do this?

  • Would I give something like self.itens.joins(:avaliacoes).where("avaliacoes.avaliacao = ?", true)?

2 answers

2

I had the idea of trying to do directly in the bank to simplify the process and modified the function to:

def likes
  query = "SELECT itm.id
           FROM   avaliacoes av INNER JOIN itens itm ON av.item_id = itm.id
           WHERE  avaliacao is true and
                usuario_id = #{self.id}"
  Usuario.connection.execute(query).to_set
end

I’ve had a 0.2 second average improvement... I’m putting as an answer because I don’t think I can improve more than that, but if anyone wants to prove me otherwise the answer will be very welcome!

  • I use the method of like and dislike to find the similarity between users. Maturing here, I think a better solution would be to assemble an array[][] of user similarity x user and leave as attribute of the User model, so when needed would only use matrix[user1.id - 1][user2.id - 1]. What do you think?

0

Wouldn’t it be less expensive if you did it paged ? You can use the library https://github.com/mislav/will_paginate so will return the paginated items I believe will decrease the search time.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.