Recherche de données sérialisées à l’aide d’un enregistrement actif

J’essaie de faire une simple requête sur une colonne sérialisée, comment faites-vous cela?

serialize :mycode, Array 1.9.3p125 :026 > MyModel.find(104).mycode MyModel Load (0.6ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`id` = 104 LIMIT 1 => [43565, 43402] 1.9.3p125 :027 > MyModel.find_all_by_mycode("[43402]") MyModel Load (0.7ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` = '[43402]' => [] 1.9.3p125 :028 > MyModel.find_all_by_mycode(43402) MyModel Load (1.2ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` = 43402 => [] 1.9.3p125 :029 > MyModel.find_all_by_mycode([43565, 43402]) MyModel Load (1.1ms) SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` IN (43565, 43402) => [] 

En gros, vous ne pouvez pas. L’inconvénient de #serialize est que vous ignorez les abstractions natives de votre firebase database. Vous êtes quasiment limité au chargement et à la sauvegarde des données.

Cela dit, un très bon moyen de ralentir votre application à une parsing pourrait être:

 MyModel.all.select { |m| m.mycode.include? 43402 } 

Morale de l’histoire: n’utilisez pas #serialize pour toutes les données dont vous avez besoin pour interroger.

C’est juste un truc pour ne pas ralentir votre application. Vous devez utiliser .to_yaml .

résultat exact:

 MyModel.where("mycode = ?", [43565, 43402].to_yaml) #=> [# 

Testé uniquement pour MySQL.

Le tableau sérialisé est stocké dans la firebase database de manière particulière, par exemple:

 [1, 2, 3, 4] in 1\n 2\n 3\n etc 

donc la requête serait

 MyModel.where("mycode like ?", "% 2\n%") 

mettre un espace entre % et 2 .

La réponse de Noodl est correcte, mais pas tout à fait correcte.

Cela dépend vraiment de l’adaptateur de firebase database / ORM que vous utilisez: par exemple, PostgreSQL ™ peut désormais stocker et rechercher les hashes / json – consultez hstore. Je me souviens d’avoir lu que l’adaptateur ActiveRecord pour PostgreSQl le gère maintenant correctement. Et si vous utilisez mongoid ou quelque chose comme ça – alors vous utilisez des données non structurées (c.-à-d. Json) au niveau de la firebase database partout.

Cependant, si vous utilisez une firebase database qui ne supporte pas vraiment les hachages – comme la combinaison MySQL / ActiveRecord – alors la seule raison pour laquelle vous utiliseriez un champ sérialisé est que certaines données peuvent être créées / écrites dans certains processus en arrière-plan. – les deux seules utilisations que j’ai trouvées dans mon expérience sont des rapports (comme un champ de statistiques sur un modèle de produit – où je dois stocker des moyennes et des médianes pour un produit) et des options utilisateur pas besoin d’interroger à ce sujet) – cependant, les informations utilisateur – comme leur abonnement à une liste de diffusion – doivent pouvoir être recherchées pour les envois par courrier électronique.

Exemple de PostgreSQL hstore ActiveRecord:

 MyModel.where("mycode @> 'KEY=>\"#{VALUE}\"'") 

Bonnes nouvelles! Si vous utilisez PostgreSQL avec hstore (ce qui est très facile avec Rails 4), vous pouvez désormais rechercher des données sérialisées. Ceci est un guide pratique, et voici la documentation de la syntaxe de PG.

Dans mon cas, j’ai un dictionnaire stocké sous forme de hachage dans une colonne hstore appelée amenities . Je veux vérifier pour un couple de commodités interrogées qui ont une valeur de 1 dans le hash, je fais juste

 House.where("amenities @> 'wifi => 1' AND amenities @> 'pool => 1'") 

Hourra pour les améliorations!

Vous pouvez interroger la colonne sérialisée avec une instruction sql LIKE.

  MyModel.where("mycode LIKE '%?%'", 43402) 

C’est plus rapide que d’utiliser include, cependant, vous ne pouvez pas utiliser un tableau comme paramètre.

Il y a un billet de blog de 2009 de FriendFeed qui décrit comment utiliser les données sérialisées dans MySQL.

Ce que vous pouvez faire, c’est créer des tables qui fonctionnent comme des index pour toutes les données que vous souhaitez rechercher.

Créer un modèle contenant les valeurs / champs consultables

Dans votre exemple, les modèles ressemblent à ceci:

 class MyModel < ApplicationRecord # id, name, other fields... serialize :mycode, Array end class Item < ApplicationRecord # id, value... belongs_to :my_model end 

Création d'une table "index" pour les champs de recherche

Lorsque vous enregistrez MyModel, vous pouvez faire quelque chose comme cela pour créer l'index:

 Item.where(my_model: self).destroy self.mycode.each do |mycode_item| Item.create(my_model: self, value: mycode_item) end 

Interrogation et recherche

Ensuite, lorsque vous souhaitez interroger et rechercher, procédez comme suit:

 Item.where(value: [43565, 43402]).all.map(&:my_model) Item.where(value: 43402).all.map(&:my_model) 

Vous pouvez append une méthode à MyModel pour simplifier les choses:

 def find_by_mycode(value_or_values) Item.where(value: value_or_values).all.map(&my_model) end MyModel.find_by_mycode([43565, 43402]) MyModel.find_by_mycode(43402) 

Pour accélérer les choses, vous souhaiterez créer un index SQL pour cette table.