Commit 4f16e22c authored by Koen van der Veen's avatar Koen van der Veen
Browse files

let uid generation be handled by the pod

parent 6354d52d
Showing with 113 additions and 82 deletions
+113 -82
......@@ -60,4 +60,4 @@ sidebars:
- home_sidebar
theme: jekyll-theme-cayman
baseurl: /integrators
baseurl: /integrators/
......@@ -47,7 +47,7 @@ nb_path: "nbs/itembase.ipynb"
<div class="output_markdown rendered_html output_subarea ">
<h2 id="Edge" class="doc_header"><code>class</code> <code>Edge</code><a href="https://gitlab.memri.io/memri/integrators/tree/master/integrators/itembase.py#L68" class="source_link" style="float:right">[source]</a></h2><blockquote><p><code>Edge</code>(<strong><code>source</code></strong>, <strong><code>target</code></strong>, <strong><code>_type</code></strong>, <strong><code>label</code></strong>=<em><code>None</code></em>, <strong><code>sequence</code></strong>=<em><code>None</code></em>, <strong><code>created</code></strong>=<em><code>False</code></em>, <strong><code>reverse</code></strong>=<em><code>True</code></em>)</p>
<h2 id="Edge" class="doc_header"><code>class</code> <code>Edge</code><a href="https://gitlab.memri.io/memri/integrators/tree/master/integrators/itembase.py#L60" class="source_link" style="float:right">[source]</a></h2><blockquote><p><code>Edge</code>(<strong><code>source</code></strong>, <strong><code>target</code></strong>, <strong><code>_type</code></strong>, <strong><code>label</code></strong>=<em><code>None</code></em>, <strong><code>sequence</code></strong>=<em><code>None</code></em>, <strong><code>created</code></strong>=<em><code>False</code></em>, <strong><code>reverse</code></strong>=<em><code>True</code></em>)</p>
</blockquote>
</div>
......@@ -78,7 +78,7 @@ nb_path: "nbs/itembase.ipynb"
<div class="output_markdown rendered_html output_subarea ">
<h2 id="ItemBase" class="doc_header"><code>class</code> <code>ItemBase</code><a href="https://gitlab.memri.io/memri/integrators/tree/master/integrators/itembase.py#L111" class="source_link" style="float:right">[source]</a></h2><blockquote><p><code>ItemBase</code>(<strong><code>uid</code></strong>=<em><code>None</code></em>)</p>
<h2 id="ItemBase" class="doc_header"><code>class</code> <code>ItemBase</code><a href="https://gitlab.memri.io/memri/integrators/tree/master/integrators/itembase.py#L103" class="source_link" style="float:right">[source]</a></h2><blockquote><p><code>ItemBase</code>(<strong><code>uid</code></strong>=<em><code>None</code></em>)</p>
</blockquote>
</div>
......
......@@ -135,7 +135,40 @@ nb_path: "nbs/pod.client.ipynb"
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">email_item</span> <span class="o">=</span> <span class="n">EmailMessage</span><span class="o">.</span><span class="n">from_data</span><span class="p">(</span><span class="n">content</span><span class="o">=</span><span class="s2">&quot;example content field&quot;</span><span class="p">)</span>
<span class="n">success</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">email_item</span><span class="p">)</span>
<span class="n">email_item</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>EmailMessage (#None)</pre>
</div>
</div>
</div>
</div>
</div>
{% endraw %}
{% raw %}
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">success</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">email_item</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">success</span>
<span class="n">email_item</span>
</pre></div>
......@@ -152,7 +185,7 @@ nb_path: "nbs/pod.client.ipynb"
<div class="output_text output_subarea output_execute_result">
<pre>EmailMessage (#279001)</pre>
<pre>EmailMessage (#917040)</pre>
</div>
</div>
......@@ -199,7 +232,7 @@ nb_path: "nbs/pod.client.ipynb"
<div class="output_text output_subarea output_execute_result">
<pre>Person (#279002) --author-&gt; EmailMessage (#279001)</pre>
<pre>Person (#917041) --author-&gt; EmailMessage (#917040)</pre>
</div>
</div>
......@@ -234,6 +267,7 @@ nb_path: "nbs/pod.client.ipynb"
<span class="n">client</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">person_item</span><span class="p">)</span>
<span class="n">person_from_db</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">person_item</span><span class="o">.</span><span class="n">uid</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">person_from_db</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
<span class="k">assert</span> <span class="n">person_from_db</span> <span class="o">==</span> <span class="n">person_item</span>
<span class="n">person_from_db</span>
</pre></div>
......@@ -249,7 +283,7 @@ nb_path: "nbs/pod.client.ipynb"
<div class="output_text output_subarea output_execute_result">
<pre>Person (#279003)</pre>
<pre>Person (#917042)</pre>
</div>
</div>
......@@ -294,7 +328,7 @@ nb_path: "nbs/pod.client.ipynb"
<div class="output_text output_subarea output_execute_result">
<pre>Person (#279003)</pre>
<pre>Person (#917042)</pre>
</div>
</div>
......
......@@ -9,7 +9,6 @@ index = {"read_file": "basic.ipynb",
"Indexer": "indexers.indexer.ipynb",
"ALL_EDGES": "itembase.ipynb",
"UID_GEN": "itembase.ipynb",
"generate_uid": "itembase.ipynb",
"DB": "itembase.ipynb",
"parse_base_item_json": "itembase.ipynb",
"Edge": "itembase.ipynb",
......
# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/itembase.ipynb (unless otherwise specified).
__all__ = ['ALL_EDGES', 'UID_GEN', 'generate_uid', 'DB', 'parse_base_item_json', 'Edge', 'ItemBase']
__all__ = ['ALL_EDGES', 'UID_GEN', 'DB', 'parse_base_item_json', 'Edge', 'ItemBase']
# Cell
# hide
......@@ -10,14 +10,6 @@ ALL_EDGES = "allEdges"
SOURCE, TARGET, TYPE, EDGE_TYPE, LABEL, SEQUENCE = "_source", "_target", "_type", "_type", "label", "sequence"
UID_GEN= 10000 + (random.randint(0, 1e3) * 1000)
# Cell
# hide
def generate_uid():
# TODO: REFACTOR
global UID_GEN
UID_GEN += 1
return UID_GEN
# Cell
# hide
class DB():
......@@ -113,18 +105,13 @@ class ItemBase():
def __init__(self, uid=None):
self.uid=uid
self.add_to_db(self)
existing = self.global_db.get(uid)
if existing is not None:
if not existing.is_expanded() and self.is_expanded():
# TODO: implement copying edges
existing.edges = self.edges
self.replace_self(existing)
else:
if uid is None:
self.uid = generate_uid()
self.global_db.add(self)
@classmethod
def add_to_db(cls, node):
existing = cls.global_db.get(node.uid)
if existing is None and node.uid is not None:
cls.global_db.add(node)
def replace_self(self, other):
self.__dict__.update(other.__dict__)
......@@ -211,8 +198,6 @@ class ItemBase():
edges = dict()
new_kwargs = dict()
for k, v in kwargs.items():
# import ipdb
# ipdb.set_trace()
if isinstance(v, ItemBase):
edge = Edge(None, v, k)
edges[k] = edge
......
......@@ -3,7 +3,7 @@
__all__ = ['API_URL', 'PodClient']
# Cell
from ..itembase import Edge
from ..itembase import Edge, ItemBase
from ..schema import *
from ..imports import *
......@@ -19,7 +19,6 @@ class PodClient:
self.test_connection(verbose=False)
self.database_key=database_key
self.owner_key=owner_key
# self.local_db = DB()
def test_connection(self, verbose=True):
try:
......@@ -30,13 +29,9 @@ class PodClient:
print("Could no connect to backend")
return False
# def uid(self):
# # TODO: REFACTOR
# return int(1e5 + random.randint(0, 1e5))
def create(self, node):
if node.uid is None:
print(f"Error, node {node} has no uid, not creating")
# if node.uid is None:
# print(f"Error, node {node} has no uid, not creating")
try:
body = { "databaseKey": self.database_key, "payload":self.get_properties_json(node) }
......@@ -46,6 +41,9 @@ class PodClient:
print(result, result.content)
return False
else:
uid = int(result.json())
node.uid = uid
ItemBase.add_to_db(node)
return True
except requests.exceptions.RequestException as e:
print(e)
......@@ -167,7 +165,15 @@ class PodClient:
def item_from_json(self, json):
indexer_class = json.get("indexerClass", None)
constructor = get_constructor(json["_type"], indexer_class)
return constructor.from_json(json)
new_item = constructor.from_json(json)
existing = ItemBase.global_db.get(new_item.uid)
# TODO: cleanup
if existing is not None:
if not existing.is_expanded() and new_item.is_expanded():
existing.edges = new_item.edges
return existing
else:
return item
def get_properties(self, expanded):
properties = copy(expanded)
......
%% Cell type:code id: tags:
``` python
%load_ext autoreload
%autoreload 2
# default_exp itembase
```
%% Cell type:markdown id: tags:
# Itembase
%% Cell type:code id: tags:
``` python
# export
# hide
from integrators.imports import *
ALL_EDGES = "allEdges"
SOURCE, TARGET, TYPE, EDGE_TYPE, LABEL, SEQUENCE = "_source", "_target", "_type", "_type", "label", "sequence"
UID_GEN= 10000 + (random.randint(0, 1e3) * 1000)
```
%% Cell type:code id: tags:
``` python
# export
# hide
def generate_uid():
# TODO: REFACTOR
global UID_GEN
UID_GEN += 1
return UID_GEN
```
%% Cell type:code id: tags:
``` python
# export
# hide
class DB():
def __init__(self):
self.nodes = dict()
def add(self, node):
uid = node.uid
if uid in self.nodes:
print(f"Error trying to add node, but node with with UID: {uid} is already in database")
self.nodes[uid] = node
def get(self, uid):
res = self.nodes.get(uid, None)
return res
def contains(node):
uid = node.get_property("uid")
return uid in self.nodes
def create(self, node):
existing = self.get(node.properties.get("uid", None))
if existing is not None:
if not existing._expanded:
existing.edges = node.edges
existing._expanded = node.edges is not None
return existing
else:
self.add(node)
return node
def parse_base_item_json(json):
uid = json.get("uid", None)
dateAccessed = json.get("dateAccessed", None)
dateCreated = json.get("dateCreated", None)
dateModified = json.get("dateModified", None)
deleted = json.get("deleted", None)
externalId = json.get("externalId", None)
itemDescription = json.get("itemDescription", None)
starred = json.get("starred", None)
version = json.get("version", None)
return uid, dateAccessed, dateCreated, dateModified, deleted, externalId, itemDescription, starred, version, None, None
```
%% Cell type:code id: tags:
``` python
# export
class Edge():
def __init__(self, source, target, _type, label=None, sequence=None, created=False, reverse=True):
self.source = source
self.target = target
self._type = _type
self.label = label
self.sequence = sequence
self.created = created
self.reverse = reverse
@classmethod
def from_json(cls, json):
from .schema import get_constructor
# we only set the target here
_type = json[EDGE_TYPE]
json_target = json[TARGET]
target_type = json_target["_type"]
indexer_class = json_target.get("indexerClass", None)
target_constructor = get_constructor(target_type, indexer_class)
target = target_constructor.from_json(json_target)
return cls(source=None, target=target, _type=_type)
def __repr__(self):
return f"{self.source} --{self._type}-> {self.target}"
def update(self, api):
if self.created:
api.create_edges([self])
def __eq__(self, other):
return self.source is other.source and self.target is other.target \
and self._type == other._type
def traverse(self, start):
if start == self.source:
return self.target
elif start == self.target:
return self.source
else:
raise ValueError
```
%% Cell type:code id: tags:
``` python
# export
class ItemBase():
global_db = DB()
def __init__(self, uid=None):
self.uid=uid
self.add_to_db(self)
existing = self.global_db.get(uid)
if existing is not None:
if not existing.is_expanded() and self.is_expanded():
# TODO: implement copying edges
existing.edges = self.edges
self.replace_self(existing)
else:
if uid is None:
self.uid = generate_uid()
self.global_db.add(self)
@classmethod
def add_to_db(cls, node):
existing = cls.global_db.get(node.uid)
if existing is None and node.uid is not None:
cls.global_db.add(node)
def replace_self(self, other):
self.__dict__.update(other.__dict__)
def __getattribute__(self, name):
val = object.__getattribute__(self, name)
if isinstance(val, Edge):
edge = val
return edge.traverse(start=self)
if isinstance(val, list) and len(val) > 0 and isinstance(val[0], Edge):
edges = val
return [edge.traverse(start=self) for edge in edges]
else:
return val
def add_edge(self, name, val):
val = Edge(self, val, name, created=True)
if name not in self.__dict__:
raise NameError(f"object {self} does not have edge with name {name}")
existing = object.__getattribute__(self, name)
res = existing + [val]
self.__setattr__(name, res)
def is_expanded(self):
if "_expanded" in self.__dict__:
return self._expanded
else:
return False
# def __setattr__(self, name, val):
# if isinstance(val, ItemBase) or self.attr_is_edge(val):
# raise ValueError("Don't set edges directly, use node.add_edge instead")
# super().__setattr__(name, val)
def get_edges(self, name):
return object.__getattribute__(self, name)
def get_all_edges(self):
return [e for attr in self.__dict__.values() if self.attr_is_edge(attr) for e in attr]
def get_all_edge_names(self):
return [k for k,v in self.__dict__.items() if self.attr_is_edge(v)]
@staticmethod
def attr_is_edge(attr):
return isinstance(attr, list) and len(attr)>0 and isinstance(attr[0], Edge)
def update(self, api, edges=True, create_if_not_exists=True, skip_nodes=False):
if not self.exists(api):
print(f"creating {self}")
api.create(self)
else:
print(f"updating {self}")
api.put(self)
if edges:
for e in self.get_all_edges():
e.update(api)
def exists(self, api):
res = api.search_by_fields({"uid": self.uid})
return len(res) == 1
def expand(self, api):
self._expanded = True
res = api.get(self.uid, expanded=True)
for edge_name in res.get_all_edge_names():
edges = res.get_edges(edge_name)
for e in edges:
e.source = self
self.__setattr__(edge_name, edges)
# self.edges = res.edges
return self
def __repr__(self):
uid = self.uid
_type = self.__class__.__name__
return f"{_type} (#{uid})"
@classmethod
def from_data(cls, *args, **kwargs):
edges = dict()
new_kwargs = dict()
for k, v in kwargs.items():
# import ipdb
# ipdb.set_trace()
if isinstance(v, ItemBase):
edge = Edge(None, v, k)
edges[k] = edge
new_kwargs[k] = edge
else:
new_kwargs[k] = v
res = cls(*args, **new_kwargs)
for v in edges.values():
v.source = res
return res
```
%% Cell type:markdown id: tags:
With the Item and Edge classes we can create an item and its surrounding graph. The schema is defined in schema.py, in general we want to use the from_data staticmethod to generate new items, because it ensures that edges are linked from both the source and the target object. Let's make an email item and create it in the pod.
%% Cell type:code id: tags:
``` python
# hide
from integrators.schema import *
```
%% Cell type:code id: tags:
``` python
item = EmailMessage.from_data(content="example content field")
```
%% Cell type:markdown id: tags:
# Export -
%% Cell type:code id: tags:
``` python
# hide
from nbdev.export import *
notebook2script()
```
%% Output
Converted basic.ipynb.
Converted index.ipynb.
Converted indexers.indexer.ipynb.
Converted itembase.ipynb.
Converted pod.client.ipynb.
......
%% Cell type:code id: tags:
``` python
%load_ext autoreload
%autoreload 2
# default_exp pod.client
```
%% Cell type:markdown id: tags:
# Pod Client
%% Cell type:code id: tags:
``` python
# export
from integrators.itembase import Edge
from integrators.itembase import Edge, ItemBase
from integrators.schema import *
from integrators.imports import *
```
%% Cell type:code id: tags:
``` python
# export
API_URL = "http://localhost:3030/v2"
```
%% Cell type:code id: tags:
``` python
# export
class PodClient:
def __init__(self, url=API_URL, database_key=None, owner_key=None):
self.url = url
self.base_url = f"{url}/{owner_key}"
self.test_connection(verbose=False)
self.database_key=database_key
self.owner_key=owner_key
# self.local_db = DB()
def test_connection(self, verbose=True):
try:
res = requests.get(self.url)
if verbose: print("Succesfully connected to pod")
return True
except requests.exceptions.RequestException as e:
print("Could no connect to backend")
return False
# def uid(self):
# # TODO: REFACTOR
# return int(1e5 + random.randint(0, 1e5))
def create(self, node):
if node.uid is None:
print(f"Error, node {node} has no uid, not creating")
# if node.uid is None:
# print(f"Error, node {node} has no uid, not creating")
try:
body = { "databaseKey": self.database_key, "payload":self.get_properties_json(node) }
result = requests.post(f"{self.base_url}/create_item",
json=body)
if result.status_code != 200:
print(result, result.content)
return False
else:
uid = int(result.json())
node.uid = uid
ItemBase.add_to_db(node)
return True
except requests.exceptions.RequestException as e:
print(e)
return False
def create_edges(self, edges):
"""Create edges between nodes, edges should be of format [{"_type": "friend", "_source": 1, "_target": 2}]"""
edges_data = []
for e in edges:
src, target = e.source.uid, e.target.uid
data = {"_source": src, "_target": target, "_type": e._type}
if e.label is not None: data[LABEL] = e.label
if e.sequence is not None: data[SEQUENCE] = e.sequence
if e.reverse:
data2 = copy(data)
data2["_source"] = target
data2["_target"] = src
data2["_type"] = "~" + data2["_type"]
edges_data.append(data2)
edges_data.append(data)
edges_data = {"databaseKey": self.database_key, "payload": {
"createItems": [], "updateItems": [], "createEdges": edges_data}}
try:
result = requests.post(f"{self.base_url}/bulk_action",
json=edges_data)
if result.status_code != 200:
if "UNIQUE constraint failed" in str(result.content):
print(result.status_code, "Edge already exists")
else:
print(result, result.content)
return False
else:
return True
except requests.exceptions.RequestException as e:
print(e)
return False
def create_edge(self, edge):
return self.create_edges([edge])
def get(self, uid, expanded=True):
if not expanded:
return self._get_item_with_properties(uid)
else:
return self._get_item_expanded(uid)
def _get_item_expanded(self, uid):
body = {"payload": [uid],
"databaseKey": self.database_key}
try:
result = requests.post(f"{self.base_url}/get_items_with_edges",
json=body)
if result.status_code != 200:
print(result, result.content)
return None
else:
json = result.json()[0]
res = self.item_from_json(json)
return res
except requests.exceptions.RequestException as e:
print(e)
return None
def _get_item_with_properties(uid):
try:
result = requests.get(f"{self.base_url}/items/{uid}")
if result.status_code != 200:
print(result, result.content)
return None
else:
json = result.json()
if json == []:
return None
else:
return json
except requests.exceptions.RequestException as e:
print(e)
return None
def get_properties_json(self, node):
res = dict()
for k,v in node.__dict__.items():
if k[:1] != '_' and not (isinstance(v, list) and len(v)>0 and isinstance(v[0], Edge)) and v is not None:
res[k] = v
res["_type"] = node.__class__.__name__
return res
def update_item(self, node):
data = self.get_properties_json(node)
uid = data["uid"]
body = {"payload": data,
"databaseKey": self.database_key}
try:
result = requests.post(f"{self.base_url}/update_item",
json=body)
if result.status_code != 200:
print(result, result.content)
except requests.exceptions.RequestException as e:
print(e)
def search_by_fields(self, fields_data):
body = {"payload": fields_data,
"databaseKey": self.database_key}
try:
result = requests.post(f"{self.base_url}/search_by_fields",
json=body)
json = result.json()
return [self.item_from_json(item) for item in json]
except requests.exceptions.RequestException as e:
return None
def item_from_json(self, json):
indexer_class = json.get("indexerClass", None)
constructor = get_constructor(json["_type"], indexer_class)
return constructor.from_json(json)
new_item = constructor.from_json(json)
existing = ItemBase.global_db.get(new_item.uid)
# TODO: cleanup
if existing is not None:
if not existing.is_expanded() and new_item.is_expanded():
existing.edges = new_item.edges
return existing
else:
return item
def get_properties(self, expanded):
properties = copy(expanded)
if ALL_EDGES in properties: del properties[ALL_EDGES]
return properties
def run_importer(self, uid, servicePayload):
body = dict()
body["databaseKey"] = servicePayload["databaseKey"]
body["payload"] = {"uid": uid, "servicePayload": servicePayload}
print(body)
try:
res = requests.post(f"{self.base_url}/run_importer", json=body)
# res = requests.post(self.url)
if res.status_code != 200:
print(f"Failed to start importer on {url}:\n{res.status_code}: {res.text}")
else:
print("Starting importer")
except requests.exceptions.RequestException as e:
print("Error with calling importer {e}")
```
%% Cell type:markdown id: tags:
We communicate with the pod with the PodClient. The PodClient requires us to provide a [database key](https://gitlab.memri.io/memri/pod/-/blob/dev/docs/HTTP_API.md#user-content-api-authentication-credentials) and an [owner key](https://gitlab.memri.io/memri/pod/-/blob/dev/docs/HTTP_API.md#user-content-api-authentication-credentials). You don't have to worry about these keys: when you run an Integrator from a memri client, this goes via the pod, which provides these keys for you. For testing purposes, we can make our own keys.
%% Cell type:code id: tags:
``` python
client = PodClient(database_key="0" * 64, owner_key="1" * 64)
success = client.test_connection()
assert success
```
%% Output
Succesfully connected to pod
%% Cell type:markdown id: tags:
## Creating Items and Edges
%% Cell type:markdown id: tags:
Now that we have access to the pod, we can create items here and upload them to the pod. All items are defined in the memri [schema](https://gitlab.memri.io/memri/schema). When the schema is changed it automatically generates all the class definitions for the different languages used in memri, the python schema file lives in [schema.py](https://gitlab.memri.io/memri/pyintegrators/-/blob/master/integrators/schema.py) in the integrators package. When Initializing an Item, always make sure to use the from_data classmethod to initialize.
%% Cell type:code id: tags:
``` python
email_item = EmailMessage.from_data(content="example content field")
email_item
```
%% Output
EmailMessage (#None)
%% Cell type:code id: tags:
``` python
success = client.create(email_item)
assert success
email_item
```
%% Output
EmailMessage (#279001)
EmailMessage (#917040)
%% Cell type:markdown id: tags:
We can connect items using edges. Let's create another item, a person, and connect the email and the person.
%% Cell type:code id: tags:
``` python
person_item = Person.from_data(firstName="Alice")
item_succes = client.create(person_item)
edge = Edge(person_item, email_item, "author")
edge_succes = client.create_edge(edge)
assert item_succes and edge_succes
edge
```
%% Output
Person (#279002) --author-> EmailMessage (#279001)
Person (#917041) --author-> EmailMessage (#917040)
%% Cell type:markdown id: tags:
# Fetching and updating Items
%% Cell type:markdown id: tags:
We can use the client to fetch data from the database. This is in particular usefull for indexers, which often use data in the database as input for their models. The simplest form of querying the database is by querying items in the pod by their uid (unique identifier).
%% Cell type:code id: tags:
``` python
person_item = Person.from_data(firstName="Alice")
client.create(person_item)
person_from_db = client.get(person_item.uid)
assert person_from_db is not None
assert person_from_db == person_item
person_from_db
```
%% Output
Person (#279003)
Person (#917042)
%% Cell type:markdown id: tags:
Appart from creating, we might want to update existing items:
%% Cell type:code id: tags:
``` python
person_item.lastName = "Awesome"
client.update_item(person_item)
person_from_db = client.get(person_item.uid)
assert person_from_db.lastName == "Awesome"
person_from_db
```
%% Output
Person (#279003)
Person (#917042)
%% Cell type:markdown id: tags:
Sometimes, we might not know the uids of the items we want to fetch. We can also search by a certain property. We can use this for instance when we want to query all items from a particular type to perform some indexing on.
%% Cell type:code id: tags:
``` python
person_item2 = Person.from_data(firstName="Bob")
client.create(person_item2);
all_people = client.search_by_fields({"_type": "Person"})
assert all([isinstance(p, Person) for p in all_people]) and len(all_people) > 0
all_people[:3]
```
%% Output
[Person (#32002), Person (#32004), Person (#32005)]
%% Cell type:markdown id: tags:
# Export -
%% Cell type:code id: tags:
``` python
# hide
from nbdev.export import *
notebook2script()
```
%% Output
Converted basic.ipynb.
Converted index.ipynb.
Converted indexers.indexer.ipynb.
Converted itembase.ipynb.
Converted pod.client.ipynb.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment