Standard Operations
Read, Write, and Delete
The core building blocks of Artigraph can be interacted with using the following functions.
Object-based functions | Query-based functions |
---|---|
delete_many() | delete() |
delete_one() | exists() |
write_many() | read() |
write_one() | read_one() |
Object-based Functions
The object-based functions take GraphObjects as arguments and either write them to the database or delete them from the database. Usage tends to look like this:
Query-based Functions
The query-based functions take Filter objects (learn more) as arguments and either read or delete objects from the database. Usage tends to look like this:
import artigraph as ag
node = ag.Node()
ag.write_one(node)
node = ag.read_one(ag.NodeFilter(id=node.graph_id))
ag.delete(ag.NodeFilter(id=node.graph_id))
Sessions
By default, Artigraph will create a new database session for each function call you make. This is fine for most use cases, but if you're making a lot of calls to the database, it can be more efficient to use a single session for all of your calls. You can do this by using the current_session() context manager:
import artigraph as ag
with ag.current_session() as session:
node = ag.Node()
ag.write_one(node)
node = ag.read_one(ag.NodeFilter(id=node.graph_id))
ag.delete_one(node)
Async Usage
Artigraph is designed for both synchronous and asynchronous usage. To allow for this, Artigraph uses a bit of magic to figure out if it should run synchronously or asynchronously depending on the context. In short, if there's a running event loop, Artigraph will run asynchronously, and if there's not, it will do so synchronously.
Note
Jupyter Notebooks and IPython shells have a running event loop by default. If you're using Artigraph in a Jupyter Notebook or IPython shell, you'll need to call Artigraph functions asynchronously.
For example, write_one() can be used synchronously like this:
While asynchronous use looks like this:
import asyncio
import artigraph as ag
async def main():
node = ag.Node()
await ag.write_one(node)
asyncio.run(main())
Context managers also work in both synchronous and asynchronous contexts:
And the async counter-part:
import asyncio
async def main():
async with ag.current_session() as session:
...
asyncio.run(main())
Explicit Sync or Async Usage
Sometimes you may run into situations where the implicit sync or async behavior
described above doesn't work for you. For example, you need to call one of these
functions synchronously even though there's a running event loop. In these cases, you
can force Artigraph to use the sync or async version of a function by accessing the .a
or .s
attributes of the function you're calling.
For example, if you needed to use the synchronous version of write_one in the presebnce of a running event loop, you can do so like this:
import asyncio
import artigraph as ag
async def main():
node = ag.Node()
ag.write_one.s(node)
asyncio.run(main())
Being able to be explicit about whether you're using a sync or async version of a
function can also be useful when working with type checkers since the return type of the
dual-use function (without the .a
or .s
) will be the union Awaitable[T] | T
where
T
is the return type of the function.