12

我是 SQLAlchemy 的新手(但不是那么新)。我正在为一个项目使用 0.9.3 版本。我想查询 SQLite 数据库过滤结果以获取那些没有时间戳或自上次更新以来超过 24 小时的对象(在同一列上)。

问题是,我不知道如何实现时间过滤部分,我做了一个 IPython Notebook 会话,所以人们可以看看尝试寻找我的问题的答案多长时间:

在 [1] 中:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Unicode, DateTime, Integer, create_engine
from sqlalchemy.orm import sessionmaker, relationship, backref
from datetime import datetime

engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()

在 [2] 中:

class Product(Base):
    __tablename__ = "product"

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(140), unique=True, nullable=False)
    department = Column(Unicode(20))
    added = Column(DateTime, default=datetime.now)
    last_time_parsed = Column(DateTime)

    def repr(self):
        return "<Product(name=%s, department=%s, added=%s, last_time_parsed=%s)>" % (
                            self.name, self.department, self.added, self.last_time_parsed)

在 [3] 中:

# create the tables
Base.metadata.create_all(engine)

在[4]中:

# create a false product
p1 = Product(name="Product X")
p2 = Product(name = "Product Y")
p3 = Product(name = "Product Z")

在[5]中:

session.add(p1)
session.add(p2)
session.add(p3)
session.commit()

/home/jorge/projects/project1/lib/python2.7/site-packages/sqlalchemy/engine/default.py:525: SAWarning: Unicode type received non-unicode bind param value.
  param.append(processors[key](compiled_params[key]))

在[7]中:

q = session.query(Product).filter(Product.last_time_parsed == None).filter(Product.last_time_parsed > 24)

在[9]中:

print q.first().name

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-9-377361de0bab> in <module>()
----> 1 print q.first().name

AttributeError: 'NoneType' object has no attribute 'name'

在[14]中:

q = session.query(Product).filter(Product.last_time_parsed == None)

在[15]中:

print q.first().name

Product X

在[16]中:

q = session.query(Product).filter(Product.last_time_parsed < 24)
print q.first().name

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-16-b10ccbb5d88d> in <module>()
      1 q = session.query(Product).filter(Product.last_time_parsed < 24)
----> 2 print q.first().name

AttributeError: 'NoneType' object has no attribute 'name'

在[20]中:

q = session.query(Product).filter(Product.added > 24)
print q.first().name

Product X

在 []:

input 20知道这Product.added是一个 DateTime 数据类型(我只是用来测试,因为它是唯一包含 DateTime 值的列)。我不明白的是逻辑陈述。如果是Product.added < 24(如上所示input 16)而不是Product.added > 24我将不会从数据库中获得任何对象。所以,按数字24对数据库的理解究竟是什么?24 分钟?24小时?24 秒?24天?

那么,我该如何过滤数据以获取没有时间戳或更新时间超过 24 小时的数据?

谢谢 :)

4

2 回答 2

25

您不需要使用,但子句的union简单OR部分可以:WHERE

since = datetime.now() - timedelta(hours=24)
q = (session.query(Product).filter(or_(
            Product.last_time_parsed == None,
            Product.last_time_parsed < since)))
于 2014-03-16T19:10:44.200 回答
4

所以,我发现了如何实现我想要的。感谢@univerio的更正!

我将发布整个 IPython Notebook 会话 :)

在 [1] 中:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Unicode, DateTime, Integer, create_engine
from sqlalchemy.orm import sessionmaker, relationship, backref
import datetime

engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()

在 [2] 中:

class Product(Base):
    __tablename__ = "product"

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(140), unique=True, nullable=False)
    department = Column(Unicode(20))
    added = Column(DateTime, default=datetime.datetime.now)
    last_time_parsed = Column(DateTime)

    def repr(self):
        return "<Product(name=%s, department=%s, added=%s, last_time_parsed=%s)>" % (
                            self.name, self.department, self.added, self.last_time_parsed)

在 [3] 中:

# create the tables
Base.metadata.create_all(engine)

在[4]中:

# create a false product
twodaysinthefuture = datetime.datetime.now() + datetime.timedelta(hours=48)
p1 = Product(name="Product X")
p2 = Product(name = "Product Y")
p3 = Product(name = "Product Z")
x1 = Product(name = "Product older than 24 hours 1", last_time_parsed=twodaysinthefuture)
x2 = Product(name = "Product older than 24 hours 2", last_time_parsed=twodaysinthefuture)
x3 = Product(name = "Product older than 24 hours 3", last_time_parsed=twodaysinthefuture)

在[5]中:

session.add(p1)
session.add(p2)
session.add(p3)
session.add(x1)
session.add(x2)
session.add(x3)
session.commit()

/home/jorge/coders/PPH/clientes/robert_s/playcomscrap/lib/python2.7/site-packages/sqlalchemy/engine/default.py:525: SAWarning: Unicode type received non-unicode bind param value.
  param.append(processors[key](compiled_params[key]))

在[6]中:

onedayearly = datetime.timedelta(hours=24)
print onedayearly
since = datetime.datetime.now() - onedayearly

1 day, 0:00:00

在[7]中:

q1 = session.query(Product).filter(Product.last_time_parsed < since) # filter-out those rows with less than 24 hours, right?
q2 = session.query(Product).filter(Product.last_time_parsed == None) # I'm interested on those products with no time stamp yet, too.
q3 = q1.union(q2).order_by(Product.id) # aaaaand, done!

在[8]中:

# testing
for row in q3.all():
    print row.name, row.last_time_parsed

Product X None
Product Y None
Product Z None
Product older than 24 hours 1 2014-03-17 17:26:03.899875
Product older than 24 hours 2 2014-03-17 17:26:03.899875
Product older than 24 hours 3 2014-03-17 17:26:03.899875

在 []:

于 2014-03-15T23:28:14.800 回答