Skip to content

Latest commit

 

History

History
173 lines (112 loc) · 4.51 KB

stores.rst

File metadata and controls

173 lines (112 loc) · 4.51 KB

Stores

So far, we've created items, but never actually put them in a database. Axiom "databases" are called stores.

To create a store, just call axiom.store.Store(). By default, that will create an in-memory store. Obviously, in-memory stores aren't persisted.

.. testsetup::

    from axiom.store import Store

>>> inMemoryStore = Store()

To create a persisted store, pass either a path as a string, or a twisted.python.filepath.FilePath to the store constructor:

>>> persistedStore = Store("mystore")

Adding objects to stores

You can either set an item's store when you create it, or by setting its store attribute later:

.. testsetup::

    from person import Person

>>> store = Store()
>>> alice = Person(store=store, name=u"Alice")
>>> bob = Person(name=u"Bob")
>>> bob.store = store
>>> assert alice.store is bob.store is store

Basic querying

Once we have some objects in a store, we can query them. Simple queries take the item class you want to get instances of, and the usual querying suspects:

  • comparisons (filters)
  • limits and offsets
  • sorting

The result returned by a query is a generator, so we'll call list on it to show its contents.

>>> people = list(store.query(Person, sort=Person.name.ascending))
>>> assert people == [alice, bob]
>>> person, = store.query(Person, sort=Person.name.ascending, limit=1)
>>> assert person is alice
>>> person, = store.query(Person, sort=Person.name.ascending, limit=1, offset=1)
>>> assert person is bob

Finding unique objects

Since finding exactly one object is such a common pattern, there's an easier shorthand for it called findUnique.

>>> person = store.findUnique(Person, Person.name == u"Alice")
>>> assert person is alice

Since you're expecting to find a single object, findUnique will raise an exception if there is more than one:

>>> secondAlice = Person(store=store, name=u"Alice")
>>> store.findUnique(Person, Person.name == u"Alice")
Traceback (most recent call last):
...
DuplicateUniqueItem: (person.Person.name = u'Alice', [...])

Similarly, it will raise an exception if there are none:

>>> store.findUnique(Person, Person.name == u"Nobody")
Traceback (most recent call last):
...
ItemNotFound: person.Person.name = u'Nobody'

Creating items unless they exist already

Sometimes, you want to create an object if it does not exist, or update an object if it does. Axiom calls this findOrCreate.

>>> newAlice = store.findOrCreate(Person, name=u"Alice")
>>> assert newAlice is alice, "returns the existing object"
>>> charlie = store.findOrCreate(Person, name=u"Charlie")

Getting parts of the data

Often, you only want part of the data instead of the entire stored item using getColumn. (This will once again produce a lazy iterator, so we will use list to consume it.)

.. testsetup::

    from bunny import Bunny

>>> bugs = Bunny(store=store, timesPetted=1)
>>> fluffy = Bunny(store=store, timesPetted=2)
>>> thumper = Bunny(store=store, timesPetted=3)
>>> query = store.query(Bunny, sort=Bunny.timesPetted.ascending)
>>> assert list(query.getColumn("timesPetted")) == [1, 2, 3]

Aggregate data: sums, counts, averages

You can sum over all the attributes in a store:

>>> assert store.sum(Bunny.timesPetted) == 6

Usually, it's more useful to do it over a query than over all items:

>>> query = store.query(Bunny, Bunny.timesPetted > 1).getColumn("timesPetted")
>>> assert query.sum() == 5

While you could also do this by using Python's builtin sum function to get the same result. The principal difference is that with the query method, the summing is actually done inside the database.

You can also count how many items there are in a query.

>>> assert query.count() == 2

You can also average values:

>>> assert query.average() == 2.5

Notice how we're re-using the query object. Queries are lazy: they're only executed when you actually need an item. For example, if an item is created or modified so that it suddenly is affected by the query, you get the appropriate result:

>>> bugs.timesPetted += 1
>>> assert query.count() == 3