Metadata-Version: 2.1
Name: db-join
Version: 0.0.1
Summary: NoSQL db `join`
Home-page: https://github.com/freywaid/db-join
Author: Frey Waid
Author-email: logophage1@gmail.com
License: MIT License

Copyright (c) 2021 Frey Waid

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Description: # 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`.
        
        
        ## 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.
        
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
