[PYTHON] Créez votre propre valeur composite avec SQLAlchemy

La valeur composite est un modèle dans PofEAA qui mappe un objet de valeur simple, qui est un attribut d'une entité, sous la forme de plusieurs colonnes dans la table sur laquelle l'entité est mappée.

Il existe également un modèle similaire appelé Serialized LOB, qui sérialise un objet en JSON, etc. et le place dans un BLOB ou un CLOB. La valeur composite a l'avantage de pouvoir être utilisée à partir de SQL par rapport au LOB sérialisé.

Un exemple de création de valeur composite avec SQLAlchemy peut être trouvé dans la documentation d'origine. Composite Column Types

Cependant, dans cet exemple, aucun opérateur n'est défini, donc seule la comparaison de valeurs égales est possible. Vous pouvez également personnaliser la partie de génération SQL en utilisant comparator_factory, mais comme l'échantillon de cette partie a été séparé, j'ai créé un échantillon à assembler.

Cet exemple est plus simple car il utilise un tuple nommé pour créer un objet de valeur.

composite_example.py


# -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import

from collections import namedtuple
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm.properties import CompositeProperty
from sqlalchemy.orm import composite, sessionmaker, configure_mapper

#Copier à partir du didacticiel ORM
Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(engine)


#Type de plage qui est l'objet de valeur cette fois. Il y a début et fin.
class Range(namedtuple('Range', 'start end')):

    #Cette méthode renvoie la valeur mappée dans le taple,
    #Puisque namedtuple est un tapple, il suffit de renvoyer self
    def __composite_values__(self):
        return self

    #Ceci est juste une méthode. Utiliser via un membre d'instance
    def includes(self, value):
        return self.start <= value < self.end


#C'est la personne qui génère du SQL
class RangeComparator(CompositeProperty.Comparator):
    #Méthode pour générer du SQL.Associons la méthode et l'utilisation de Value Object
    def includes(self, value):
        #Extrayez la colonne mappée. Cette partie est une copie.
        start, end = self.__clause_element__().clauses
        # and_()Générer du SQL en utilisant.
        return and_(start <= value, value < end)


#Fonction d'assistance
def range_composite(start, end):
    return composite(Range, start, end, comparator_factory=RangeComparator)


class MyTable(Base):
    __tablename__ = 'mytable'
    id = Column(Integer, primary_key=True)
    foo_start = Column(Integer)
    foo_end = Column(Integer)
    foo_range = range_composite(foo_start, foo_end)

    def __repr__(self):
        return "MyTable(foo_start={0.foo_start!r}, foo_end={0.foo_end!r}".format(self)


#Non requis pour cet échantillon.Mais pour les projets complexes, vous devez le faire
#Comme il y a des cas où la génération SQL échoue parce que le mappage qui s'étend sur plusieurs classes n'est pas terminé,
#Faisons-le après avoir défini tous les modèles.
# configure_mappers()


print("Create tables")
Base.metadata.create_all(engine)

session = Session()
print("Insert test data")
session.add(MyTable(foo_start=10, foo_end=100))
session.add(MyTable(foo_start=100, foo_end=200))
session.add(MyTable(foo_start=1, foo_end=10))
session.commit()

print("Select using filter")
# RangeComparator.includes()Peut être utilisé pour construire la partie filtre
values = session.query(MyTable).filter(MyTable.foo_range.includes(42)).all()
print("values:", values)

#Bien sûr, Range.includes()Peut être utilisé normalement dans une instance
v = values[0]
print("test")
print(9, v.foo_range.includes(9))
print(10, v.foo_range.includes(10))
print(99, v.foo_range.includes(99))
print(100, v.foo_range.includes(100))

La sortie ressemble à ceci.

Create tables
2014-01-15 22:59:15,334 INFO sqlalchemy.engine.base.Engine PRAGMA table_info("mytable")
2014-01-15 22:59:15,334 INFO sqlalchemy.engine.base.Engine ()
2014-01-15 22:59:15,335 INFO sqlalchemy.engine.base.Engine
CREATE TABLE mytable (
	id INTEGER NOT NULL,
	foo_start INTEGER,
	foo_end INTEGER,
	PRIMARY KEY (id)
)


2014-01-15 22:59:15,335 INFO sqlalchemy.engine.base.Engine ()
2014-01-15 22:59:15,335 INFO sqlalchemy.engine.base.Engine COMMIT
Insert test data
2014-01-15 22:59:15,336 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2014-01-15 22:59:15,337 INFO sqlalchemy.engine.base.Engine INSERT INTO mytable (foo_start, foo_end) VALUES (?, ?)
2014-01-15 22:59:15,337 INFO sqlalchemy.engine.base.Engine (10, 100)
2014-01-15 22:59:15,337 INFO sqlalchemy.engine.base.Engine INSERT INTO mytable (foo_start, foo_end) VALUES (?, ?)
2014-01-15 22:59:15,337 INFO sqlalchemy.engine.base.Engine (100, 200)
2014-01-15 22:59:15,338 INFO sqlalchemy.engine.base.Engine INSERT INTO mytable (foo_start, foo_end) VALUES (?, ?)
2014-01-15 22:59:15,338 INFO sqlalchemy.engine.base.Engine (1, 10)
2014-01-15 22:59:15,338 INFO sqlalchemy.engine.base.Engine COMMIT
Select using filter
2014-01-15 22:59:15,339 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2014-01-15 22:59:15,340 INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id, mytable.foo_start AS mytable_foo_start, mytable.foo_end AS mytable_foo_end
FROM mytable
WHERE mytable.foo_start <= ? AND mytable.foo_end > ?
2014-01-15 22:59:15,340 INFO sqlalchemy.engine.base.Engine (42, 42)
values: [MyTable(foo_start=10, foo_end=100]
test
9 False
10 True
99 True
100 False

Recommended Posts

Créez votre propre valeur composite avec SQLAlchemy
Créez votre propre serveur DNS avec Twisted
Créez votre propre exception
Mémo pour créer votre propre Box avec le Python de Pepper
Créez votre propre middleware Django
Apprentissage par renforcement 23 Créez et utilisez votre propre module avec Colaboratory
Créez votre propre service de résolution de noms
[Django] Créez votre propre page d'erreur 403, 404, 500
Entraînez UGATIT avec votre propre jeu de données
Résolvez votre propre labyrinthe avec DQN
Votre propre client Twitter réalisé avec Django
Créez vos propres commandes Linux en Python
[Renforcer l'apprentissage] DQN avec votre propre bibliothèque
Créez wordcloud à partir de votre tweet avec python3
[LLDB] Créez votre propre commande avec Python
Pour importer votre propre module avec jupyter
Création de la première application avec Django startproject
Publiez votre propre bibliothèque Python sur Homebrew
Créez votre propre caméra virtuelle avec Python + OpenCV et appliquez des effets originaux
Essayez de créer votre propre AWS-SDK avec bash
Créer un babillard avec Heroku, Flask, SQL Alchemy
Créez rapidement votre propre module avec setuptools (python)
Entraînez Stanford NER Tagger avec vos propres données
[Apprentissage automatique] Créez un modèle d'apprentissage automatique en effectuant un apprentissage par transfert avec votre propre ensemble de données
Créez une roue de votre propre module OpenCV
Créez votre propre lecteur de musique avec Bottle0.13 + jPlayer2.5!
Étapes pour installer votre propre bibliothèque avec pip
Flux de création de votre propre package avec setup.py avec python
Appelez votre propre bibliothèque de langage C avec Go en utilisant cgo
Créez votre propre Big Data en Python pour validation
Créez votre propre stéréogramme aléatoire (RDS) en Python.
Écrivez votre propre fonction d'activation avec Pytorch (sigmoïde dur)
Appelons votre propre bibliothèque C ++ avec Python (Préférences)
Définissez votre propre fonction de distance avec k-means de scikit-learn
[Blender x Python] Créez votre propre fonction et résumé jusqu'à présent
Créez des jeux avec Pygame
Créer un filtre avec scipy
Utiliser Enum avec SQLAlchemy
Essayez de trier vos propres objets avec des files d'attente prioritaires en Python
Exécutez l'intelligence de votre propre bibliothèque python avec VScode.
Votre URL n'a pas répondu avec la valeur du paramètre de défi.
Apprenez «l'architecture x86 apprise avec votre propre émulateur» avec Manjaro (Linux)
J'ai essayé de créer un article dans Wiki.js avec SQL Alchemy