【问题标题】:Performing multiple actions on the database through sqlalchemy query?通过 sqlalchemy 查询对数据库执行多项操作?
【发布时间】:2016-03-12 21:41:27
【问题描述】:

我有一些 sqlalchemy 模型 PersonCar 和它们的连接表。我想在给定一条数据的情况下对数据库执行多项操作,但在构建高效查询时遇到了麻烦。以下是模型:

class Person(Model):
    id = Column(Integer, primary_key=True)
    email = Column(String, unique=True)
    cars = relationship('Car', 
               secondary=persons_cars, 
               lazy='dynamic', 
               backref=db.backref('persons', lazy='dynamic')
    )

class Car(Model):
    id = Column(Integer, primary_key=True)
    name = Column(String, unique=True)


persons_cars = Table('persons_cars', 
     Column('person_id', Integer, ForeignKey('person.id'), primary_key=True),
     Column('car_id', Integer, ForeignKey('car.id'), primary_key=True)
)

如果我从 API 接收到某个人的一些数据:

{ email: 'hello@blahstuff.com',
  cars: ["audi", "honda", "toyota", "ford"]
}

那么查询应该能够:

  • 通过电子邮件获取人员。如果没有找到,创建 Person

  • 从汽车列表中,创建数据库中不存在的所有汽车。对于存在的汽车,获取它们。

  • 如果 Person 尚未拥有 Cars,则将所有 Cars 关联到 Person。

  • 将任何 Cars 与不在列表中的 Person 取消关联。

那么,如果有新的信息进来,

{ email: 'hello@blahstuff.com',
  cars: ["scion"]
}

数据库将为这个人和汽车执行必要的插入/更新/删除。

这是我写的非常幼稚的查询,非常慢:

# fetch or create the person
person = Person.query.filter_by(email=data['email'])
if person.count() == 0:
    person = Person(email=data['email'])

for car_name in data['cars']:
    r = Car.query.filter_by(name=car_name)

    # Car exists in Database, append to Person if not associated
    if r.count() > 0 and person.cars.filter_by(name=car_name).count() == 0:
        person.cars.append(r.first())

    # Car doesn't exist, so create it and append to person
    if r.count() == 0:
        person.cars.append(Car(name=car_name))

# Remove any cars that this person doesn't have anymore
for car in person.cars:
    if not car.name in data['cars']:
        person.car.remove(car)

session.add(person)
session.commit()

如何改进以提高效率?

【问题讨论】:

    标签: database python-2.7 flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    如果您的 persons_cars 表具有关于人员和汽车组合的唯一索引,那么两个明显的改进将是检查 .first() 是否存在而不是计数,以及对完整性错误使用 try-catch 子句而不是探测提前给他们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 2016-01-20
      • 1970-01-01
      相关资源
      最近更新 更多