db-join
I realized during my personal journey using Google Datastore that I was doing something very often on a set of DB entities. That is, I had foreign key references on various fields in an entity and wanted to load the entities refenced by those keys. Additionally, I wanted to control which entities are loaded with some syntactic sugar and I wanted to do it efficienntly.
Hence the birth of db-join -- a NoSQL version of join semantics you get with a SQL db.
Basics
First, create an instance of a joiner. Right now, only DatastoreJoin class exists
but I hope overtime other NoSQL dbs wrappers can be added.
>>> import join
>>> joiner = join.api.DatastoreJoin()
Next, given a iterable (typically via query), join against all the fields you wish.
>>> iterable = joiner(client, iterable, ('field1', 'field2'))
What this does is discovers if the DB keys referenced by field1 and field2 (if any)
and does a get_multi on this keys and the mutates the db object with those discovered
entities. Thus, after the join both field1 and field2 will refer to entities (instead
of keys) assuming they are in fact keys and those keys do in fact refer to db entities.
Dotted notation
These fields may actually be dotted patterns as documented in the dotted-notation
package. Dotted notation permits you to fetch an item inside a deeply nested
datastructure.
>>> d = {'hello': {'there': [{'a': 1, 'b': 2}, {'a': 7, 'b': 8}]}}
>>> dotted.get(d, 'hello.there[1].b') == 8
Thus, if your DB entity has a list of keys OR something nested you can specify how to fetch it. For example,
>>> joiner(client, iterable, 'list_of_keys[*]')
This will join on all keys contained in a list referenced by list_of_keys.
Chaining
But that's not all. A pattern may also use chaining notation:
>>> joiner(client, iterable, 'field1->another_field')
This will fetch the object at field1 and then fetch that object's the object at
another_field.
Replacing
Turns out sometimes you want to replace the object with a referenced object. The !
operator lets you do this:
>>> joiner(client, iterable, '!field1')
This will replace the object at yielded by iterable with whatever object was found
at field1. Note that this works with chaining as well.
>>> joiner(client, iterable, 'field1->!symlink')
This will replace field1 with whatever was found in symlink.
Recursive chaining
Similar to replacing, sometimes you want to recursively expand objects that are linked
via the same field. The + operator lets you do this:
>>> joiner(client, iterable, '+field')
This will fetch the object at field. If that object also has field, then it will
fetch the object at that object's field and so on until there's no more work.
Internals
A Join class has a number of abstractions to help you out. The two most important are
the getter and the setter. These methods are called whenever you're getting a value
of a field that matches pattern and when you're setting that value.
The default behavior is to just use dotted.get and dotted.update respectively.
Metadata
Release files for db-join 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| db-join-0.1.8.tar.gz | 9.1 kB | Without provenance | Details for db-join-0.1.8.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| db_join-0.1.8-py3-none-any.whl | Python 3 | none | any | Details for db_join-0.1.8-py3-none-any.whl |
Total release size: 19.1 kB
Release files / db-join-0.1.8.tar.gz
| Download URL | db-join-0.1.8.tar.gz |
|---|---|
| Size | 9.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f6205a88859446bb82d3b2231d4b88e31918ccaf74b18d3404782d15367b49f2
|
|
BLAKE2b-256 checksum How to use checksums |
f37764a19638a6e1867f5ba5997c266f0515427e1bd80f28d94c54ffccc9d219
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.0 requests/2.25.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.12
|
Release files / db_join-0.1.8-py3-none-any.whl
| Download URL | db_join-0.1.8-py3-none-any.whl |
|---|---|
| Size | 10.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a76906dd1f2d366f2d4b287fd3eb7114134090b8a6f6470af1a39f14a2ac79a1
|
|
BLAKE2b-256 checksum How to use checksums |
b15898af7924512231bdb51ba250637aa3e5d65b97ccbd189d119920b278b4d5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.0 requests/2.25.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.12
|
Security for db-join 0.1.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.