Skip to content

Commit

Permalink
Merge branch '31-restructure-examples-folder' into 'dev'
Browse files Browse the repository at this point in the history
Resolve "Restructure examples folder"

Closes #31

See merge request objectbox/objectbox-python!19
  • Loading branch information
dan-obx committed Apr 23, 2024
2 parents 33821c3 + 241be5f commit cc1256c
Show file tree
Hide file tree
Showing 9 changed files with 427 additions and 2 deletions.
3 changes: 2 additions & 1 deletion download-c-lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Script used to download objectbox-c shared libraries for all supported platforms. Execute by running `make get-lib`
# on first checkout of this repo and any time after changing the objectbox-c lib version.

version = "v0.21.0" # see objectbox/c.py required_version
version = "v0.21.1-alpha0" # see objectbox/c.py required_version
variant = 'objectbox' # or 'objectbox-sync'

base_url = "https://github.com/objectbox/objectbox-c/releases/download/"
Expand Down Expand Up @@ -49,6 +49,7 @@ def download(rel_path: str):

# Download the file from `url`, save it in a temporary directory and get the path to it (e.g. '/tmp/tmpb48zma')
source_url = url_for(rel_path);
print(f"URL {source_url}")
tmp_file, headers = urllib.request.urlretrieve(source_url)

# extract the file
Expand Down
75 changes: 75 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# ObjectBox-Python Examples

The following examples are available from this repository.

## Application Example: Tasks

This is our classic Tasks application using a CLI.

```
cd example
python -m tasks
Welcome to the ObjectBox tasks-list app example. Type help or ? for a list of commands.
> new buy oat
> new buy yeast
> new bake bread
> ls
ID Created Finished Text
1 Mon Apr 22 11:02:27 2024 buy oat
2 Mon Apr 22 11:02:30 2024 buy yeast
3 Mon Apr 22 11:02:34 2024 bake bread
> done 1
> done 2
> ls
> ls
ID Created Finished Text
1 Mon Apr 22 11:02:27 2024 Mon Apr 22 11:03:02 2024 buy oat
2 Mon Apr 22 11:02:30 2024 Mon Apr 22 11:03:18 2024 buy yeast
3 Mon Apr 22 11:02:34 2024 bake bread
> exit
```

## Vector-Search Example: Cities

This example application starts with a pre-defined set of capital cities and their geo coordinates.
It allows to search for nearest neighbors of a city (`city_neighbors`) or by coordinates (`neighbors`) as well as adding more locations (`add`).

```
python -m vectorsearch-cities
Welcome to the ObjectBox vectorsearch-cities example. Type help or ? for a list of commands.
> ls
ID Name Latitude Longitude
1 Abuja 9.08 7.40
2 Accra 5.60 -0.19
[..]
212 Yerevan 40.19 44.52
213 Zagreb 45.81 15.98
> ls Ber
ID Name Latitude Longitude
28 Berlin 52.52 13.40
29 Bern 46.95 7.45
> city_neighbors Berlin
ID Name Latitude Longitude Score
147 Prague 50.08 14.44 7.04
49 Copenhagen 55.68 12.57 10.66
200 Vienna 48.21 16.37 27.41
34 Bratislava 48.15 17.11 32.82
89 Ljubljana 46.06 14.51 42.98
> neighbors 6,52.52,13.405
ID Name Latitude Longitude Score
28 Berlin 52.52 13.40 0.00
147 Prague 50.08 14.44 7.04
49 Copenhagen 55.68 12.57 10.66
200 Vienna 48.21 16.37 27.41
34 Bratislava 48.15 17.11 32.82
89 Ljubljana 46.06 14.51 42.98
> add Area51, 37.23, -115.81
> city_neighbors Area51
ID Name Latitude Longitude Score
107 Mexico City 19.43 -99.13 594.86
27 Belmopan 17.25 -88.76 1130.92
64 Guatemala City 14.63 -90.51 1150.79
164 San Salvador 13.69 -89.22 1261.12
67 Havana 23.11 -82.37 1317.73
```
Empty file added example/tasks/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion example/__main__.py → example/tasks/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from cmd import Cmd
import objectbox
import time
from example.model import *
from .model import *


# objectbox expects date timestamp in milliseconds since UNIX epoch
Expand Down
File renamed without changes.
Empty file.
114 changes: 114 additions & 0 deletions example/vectorsearch-cities/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
from cmd import Cmd
import objectbox
import time
from .model import *
import csv
import os

def list_cities(cities):
print("{:3s} {:25s} {:>9s} {:>9s}".format("ID", "Name", "Latitude", "Longitude"))
for city in cities:
print("{:3d} {:25s} {:>9.2f} {:>9.2f}".format(
city.id, city.name, city.location[0], city.location[1]))

def list_cities_with_scores(city_score_tuples):
print("{:3s} {:25s} {:>9s} {:>9s} {:>5s}".format("ID", "Name", "Latitude", "Longitude", "Score"))
for (city,score) in city_score_tuples:
print("{:3d} {:25s} {:>9.2f} {:>9.2f} {:>5.2f}".format(
city.id, city.name, city.location[0], city.location[1], score))

class VectorSearchCitiesCmd(Cmd):
prompt = "> "
def __init__(self, *args):
Cmd.__init__(self, *args)
dbdir = "cities-db"
new_db = not os.path.exists(dbdir)
self._ob = objectbox.Builder().model(get_objectbox_model()).directory(dbdir).build()
self._box = objectbox.Box(self._ob, City)
self._name_prop: Property = City.get_property("name")
self._location_prop: Property = City.get_property("location")
if new_db:
with open(os.path.join(os.path.dirname(__file__), 'cities.csv')) as f:
r = csv.reader(f)
cities = []
for row in r:
city = City()
city.name = row[0]
city.location = [ row[1], row[2] ]
cities.append(city)
self._box.put(*cities)

def do_ls(self, name: str = ""):
"""list all cities or starting with <prefix>\nusage: ls [<prefix>]"""
qb = self._box.query()
qb.starts_with_string(self._name_prop, name)
query = qb.build()
list_cities(query.find())

def do_city_neighbors(self, args: str):
"""find <num> (default: 5) next neighbors to city <name>\nusage: city_neighbors <name> [,<num>]"""
try:
args = args.split(',')
if len(args) > 2:
raise ValueError()
city = args[0]
if len(city) == 0:
raise ValueError()
num = 5
if len(args) == 2:
num = int(args[1])
qb = self._box.query()
qb.equals_string(self._name_prop, city)
query = qb.build()
cities = query.find()
if len(cities) == 1:
location = cities[0].location
qb = self._box.query()
qb.nearest_neighbors_f32(self._location_prop, location, num+1) # +1 for the city
qb.not_equals_string(self._name_prop, city)
neighbors = qb.build().find_with_scores()
list_cities_with_scores(neighbors)
else:
print(f"no city found named '{city}'")
except ValueError:
print("usage: city_neighbors <name>[,<num: default 5>]")

def do_neighbors(self, args):
"""find <num> neighbors next to geo-coord <lat> <long>.\nusage: neighbors <num>,<latitude>,<longitude>"""
try:
args = args.split(',')
if len(args) != 3:
raise ValueError()
num = int(args[0])
geocoord = [ float(args[1]), float(args[2]) ]
qb = self._box.query()
qb.nearest_neighbors_f32(self._location_prop, geocoord, num)
neighbors = qb.build().find_with_scores()
list_cities_with_scores(neighbors)
except ValueError:
print("usage: neighbors <num>,<latitude>,<longitude>")

def do_add(self, args: str):
"""add new location\nusage: add <name>,<lat>,<long>"""
try:
args = args.split(',')
if len(args) != 3:
raise ValueError()
name = str(args[0])
lat = float(args[1])
long = float(args[2])
city = City()
city.name = name
city.location = [lat,long]
self._box.put(city)
except ValueError:
print("usage: add <name>,<latitude>,<longitude>")

def do_exit(self, _):
"""close the program"""
raise SystemExit()


if __name__ == '__main__':
app = VectorSearchCitiesCmd()
app.cmdloop('Welcome to the ObjectBox vectorsearch-cities example. Type help or ? for a list of commands.')
Loading

0 comments on commit cc1256c

Please sign in to comment.