From f9bb652034bc7a85446064f32efb558eab9b90d8 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 13 Jun 2018 02:29:32 +0200 Subject: [PATCH] add find operators --- dataset/table.py | 20 +++++++++++++++++++- docs/quickstart.rst | 18 +++++++++++++++++- test/test_dataset.py | 16 ++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/dataset/table.py b/dataset/table.py index e59dbb2..bab202a 100644 --- a/dataset/table.py +++ b/dataset/table.py @@ -2,7 +2,7 @@ import logging import warnings import threading -from sqlalchemy.sql import and_, expression +from sqlalchemy.sql import and_, between, expression from sqlalchemy.sql.expression import ClauseElement from sqlalchemy.schema import Column, Index from sqlalchemy import func, select, false @@ -293,6 +293,24 @@ class Table(object): clauses.append(false()) elif isinstance(value, (list, tuple)): clauses.append(self.table.c[column].in_(value)) + elif isinstance(value, dict): + key = list(value.keys())[0] + if key in ['like']: + clauses.append(self.table.c[column].like(value[key])) + elif key in ['>', 'gt']: + clauses.append(self.table.c[column] > value[key]) + elif key in ['<', 'lt']: + clauses.append(self.table.c[column] < value[key]) + elif key in ['>=', 'gte']: + clauses.append(self.table.c[column] >= value[key]) + elif key in ['<=', 'lte']: + clauses.append(self.table.c[column] <= value[key]) + elif key in ['!=', '<>', 'not']: + clauses.append(self.table.c[column] != value[key]) + elif key in ['between', '..']: + clauses.append(self.table.c[column].between(value[key][0], value[key][1])) + else: + clauses.append(false) else: clauses.append(self.table.c[column] == value) return and_(*clauses) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 72114cf..5edcc17 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -138,9 +138,25 @@ We can search for specific entries using :py:meth:`find() ` # Get a specific user john = table.find_one(name='John Doe') - # Find by comparison + # Find multiple at once + winners = table.find(id=[1, 3, 7]) + + # Find by comparison operator + elderly_users = table.find(age={'>=', 70}) + possible_customers = table.find(age={'between', [21, 80]}) + + # Use the underlying SQLAlchemy directly elderly_users = table.find(table.table.columns.age >= 70) +Possible comparison operators:: + + gt, > + lt, < + gte, >= + lte, <= + !=, <>, not + between, .. + Using :py:meth:`distinct() ` we can grab a set of rows with unique values in one or more columns:: diff --git a/test/test_dataset.py b/test/test_dataset.py index b9d046c..4cd0645 100644 --- a/test/test_dataset.py +++ b/test/test_dataset.py @@ -321,6 +321,22 @@ class TableTestCase(unittest.TestCase): ds = list(self.tbl.find(self.tbl.table.columns.temperature > 4)) assert len(ds) == 3, ds + def test_find_dsl(self): + ds = list(self.tbl.find(place={'like': '%lw%'})) + assert len(ds) == 3, ds + ds = list(self.tbl.find(temperature={'>': 5})) + assert len(ds) == 2, ds + ds = list(self.tbl.find(temperature={'>=': 5})) + assert len(ds) == 3, ds + ds = list(self.tbl.find(temperature={'<': 0})) + assert len(ds) == 1, ds + ds = list(self.tbl.find(temperature={'<=': 0})) + assert len(ds) == 2, ds + ds = list(self.tbl.find(temperature={'!=': -1})) + assert len(ds) == 5, ds + ds = list(self.tbl.find(temperature={'between': [5, 8]})) + assert len(ds) == 3, ds + def test_offset(self): ds = list(self.tbl.find(place=TEST_CITY_1, _offset=1)) assert len(ds) == 2, ds