2 votes

Rails ActiveRecord - Unicité et recherche sur l'attribut Array

Bonjour,

J'ai un modèle Rails dans lequel je suis en train de sérialiser un tableau d'informations. Deux choses sont importantes pour moi :

  1. Je veux pouvoir m'assurer qu'il est unique (c'est-à-dire qu'il ne peut y avoir deux modèles avec le même tableau).
  2. Je veux pouvoir rechercher des modèles existants pour ce hachage (dans une sorte de méthode find_or_create_by).

Ce modèle décrit un "portefeuille", c'est-à-dire un groupe d'actions ou d'obligations. Le tableau est la description des titres qui se trouvent dans le portefeuille, et dans quelles pondérations. J'ai également un deuxième modèle, qui est un groupe de portefeuilles (appelons-le "collection de portefeuilles" pour garder les choses simples). Une collection a plusieurs portefeuilles, et un portefeuille peut être dans plusieurs collections. En d'autres termes :

class Portfolio
  serialize :weights
  has_and_belongs_to_many :portcollections

class Portcollection
  has_and_belongs_to_many :portfolios

Lorsque je génère une "collection de portefeuilles", je dois construire un certain nombre de portefeuilles, ce que je fais de manière programmatique (l'implémentation n'est pas importante). Construire un portefeuille est une opération coûteuse, donc j'essaie de vérifier l'existence d'un portefeuille en premier lieu. Je pensais pouvoir le faire via find_or_create_by, mais je n'ai pas eu beaucoup de chance. Voici ma solution actuelle :

Class Portcollection
  before_save :build_portfolios

  def build_portfolios
    ……
    proposed_weights = ……
    yml =proposed_weights.to_yaml
    if port = Portfolio.find_by_weights(yml)
      self.portfolios << port
    else
      self.portfolios << Portfolio.create!(:weights => proposed_weights)
    end
    ……..
end

Cela fonctionne, mais c'est assez lent. J'ai l'impression que c'est parce que je convertis mes données en YAML à chaque fois que j'essaie de vérifier si un portefeuille existe (cela s'exécute probablement des millions de fois), et que je recherche une chaîne de caractères plutôt qu'un nombre entier. J'ai cependant un index sur cette colonne.

Existe-t-il une meilleure façon de procéder ? Quelques pensées m'ont traversé l'esprit :

  • Calculer un hash MD5 du tableau "weights", et le sauvegarder dans une colonne de la base de données. Je devrai toujours calculer ce hachage chaque fois que je veux rechercher un tableau, mais j'ai l'impression que ce serait plus facile pour la base de données d'indexer et de rechercher ?
  • Travailler sur le passage de has_and_belongs_to_many à has_many => through, et stocker les informations du tableau comme des colonnes de la base de données. De cette façon, je pourrais essayer d'élaborer une requête de base de données qui pourrait vérifier l'unicité, sans YAML ou sérialisation

c'est-à-dire quelque chose comme :

class Portfolio
  has_many :portcollections, :through => security_weights

class Portcollections
  has_many :portfolios, :through => security_weights

SECURITY_WEIGHTS
id     portfolio_id      portcollection_id     weight_of_GOOG  weight_of_APPLE ……
1           14                   15                   0.4           0.3

Au cas où cela serait important, le tableau des "poids" ressemblerait à ceci :

[ [‘GOOG’, 0.4] , [‘AAPL’, 0.3] , [‘GE’, 0.3] ]

Toute aide serait appréciée. N'oubliez pas que je suis un amateur - la programmation n'est qu'un passe-temps pour moi ! Veuillez m'excuser si je fais quelque chose de très compliqué ou si je manque quelque chose d'évident.....

Merci !

MISE À JOUR 1

J'ai fait quelques recherches sur la méthode "store" de Rails 3.2, mais cela ne semble pas être la solution non plus... Elle stocke simplement les objets en JSON, ce qui me donne le même manque de possibilité de recherche que maintenant.

2voto

Joel Friedlaender Points 1681

Je pense que le stockage d'un hachage séparé dans sa propre colonne est la seule façon de faire cela efficacement. Vous utilisez la sérialisation ou un magasin de clés/valeurs qui est conçu pour ne pas être facilement consultable.

Veillez simplement à trier vos valeurs avant de les hacher, sinon vous pourriez avoir le même contenu mais des hachages différents.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X