{ "info": { "author": "xxxbobrxxx, Sander Ferdinand", "author_email": "xxxbobrxxx@gmail.com, sa.ferdinand@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "SQLAlchemy support for ZomboDb\n=============================\n\n**Experimental** support for the ZomboDB query language with SQLAlchemy. Hard fork of [sqla_zdb](https://github.com/xxxbobrxxx/sqlalchemy_zombodb).\n\nPlease check out [Query Syntax](https://github.com/skftn/sqlalchemy_zdb#syntax) for an example of supported expressions.\n\n\n## What you need\n\nProduct | Version \n--- | --- \nPostgres | 9.5\nElasticsearch | 1.7.1+ (not 2.0)\nPython | 3.5+\nZomboDB | 3.1.12\n\n\n## Quick Example\n\nExample SQL table:\n\n```sql\nCREATE TABLE products (\n id SERIAL8 NOT NULL PRIMARY KEY,\n name text NOT NULL,\n keywords varchar(64)[],\n short_summary phrase,\n long_description fulltext, \n price bigint,\n inventory_count integer,\n discontinued boolean default false,\n availability_date date,\n author varchar(32)\n);\n```\n\nSQLAlchemy model:\n\n```python\nfrom sqlalchemy_zdb.types import PHRASE, FULLTEXT, ZdbColumn\n\nclass Products(base):\n __tablename__ = \"products\"\n\n id = Column(BIGINT, nullable=False, primary_key=True)\n name = Column(Unicode(), nullable=False)\n keywords = Column(ARRAY(Unicode(64)))\n short_summary = ZdbColumn(PHRASE())\n long_description = ZdbColumn(FULLTEXT(41))\n price = ZdbColumn(BIGINT())\n inventory_count = Column(Integer())\n discontinued = Column(Boolean(), default=False)\n availability_date = Column(DateTime())\n author = ZdbColumn(Unicode(32))\n```\n\n- `ZdbColumn` - Explicitly mark columns that are included in the ZomboDB index\n- `FULLTEXT` - A zomboDB specific type\n- `PHRASE` - A ZomboDB specific type\n\n`session.metadata.create_all()` correctly creates this table. It also adds the ZomboDB index.\n\n## Querying \n\n`ZdbQuery` inherits from `sqlalchemy.orm.session.Query` and you may use it as such.\n\n```python\nfrom sqlalchemy_zdb import ZdbQuery\nsession = scoped_session(sessionmaker(...))\n\nq = ZdbQuery(Products, session=session)\nq = q.filter(Products.name == \"foo\")\nq = q.filter(Products.author.like(\"bar\"))\nq = q.filter(Products.price.between(5, 10))\nq = q.filter(Products.discontinued == False)\n\nresults = q.all()\n```\n\n```sql\nSELECT [...] FROM products \nWHERE zdb('products', ctid) ==> 'author:\"bar\" and price:5 /to/ 10' AND\nproducts.name = 'foo' AND products.discontinued = false\n```\n\nNote that both the `name` and `discontinued` columns were not included in the ZomboDB query, instead they appear as valid PgSQL. This is because they were not of type `ZdbColumn` during query compilation. \n\n## Word to the wise\n\nThis extension is currently in alpha. If you decide to use this package, double check if the SQL queries generated are correct. Upon weird behaviour please submit an issue so I can look into it.\n\n## Syntax\n\n### EQUALS\n\n```python\nq = q.filter(Products.author == \"foo bar\")\n```\n\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'author:\"foo bar\"'\n```\n\nStacking 'equals' conditions on a `ZdbColumn(ARRAY(String(32)))` column:\n\n```python\nq = q.filter(Products.keywords == \"foo\")\nq = q.filter(Products.keywords == \"bar\")\n```\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'keywords:\"foo\" and keywords:\"bar\"'\n```\n\nThis would match rows that both have the `foo` AND `bar` keywords.\n\n### GT/LT\n\n```python\nq = q.filter(Products.price > 5)\n```\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'price > 5'\n```\n\n### BETWEEN\n```python\nq = q.filter(Products.price.between(5, 14.5))\n```\n\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'price:5 /to/ 14.5'\n```\n\n### LIKE\n\n```python\nq = q.filter(Products.author.like(\"foo\"))\n```\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'author:\"foo bar\"'\n```\n\nWhen passed a regex object, produces the expression: `column:~\"foo[a-z]\"`\n```python\nq = q.filter(Products.author.like(re.compile(\"foo[a-z]\")))\n```\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'author:~\"foo[a-z]\"'\n```\n\n### more_like_this\n```python\nq = q.filter(Products.author.match(\"foo\"))\n```\n\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'author:@\"foo\"'\n```\n\n### IN\n```python\nq = q.filter(Products.author.in_([\"foo\", \"bar\"]))\n```\n\n```sql\nSELECT [...] FROM products\nWHERE zdb('products', ctid) ==> 'author:(\"foo\",\"bar\")'\n```\n\nThis matches both authors named 'foo' OR 'bar'.\n\n### #LIMIT\n\nZomboDB allows you to limit the number of rows that are returned from a text query, which is similar to Postgres' `SQL-level ORDER BY LIMIT OFFSET` clauses, but can be drastically more efficient because less data is being passed around between Elasticsearch and Postgres.\n\nSyntax:\n\n```\n#limit(sort_field asc|desc, offset_val, limit_val)\n```\nE.g:\n```sql\nSELECT [...] FROM table\n WHERE zdb('table', ctid) ==> '#limit(price asc, 0, 10) ....'\nORDER BY author_name ASC;\n```\n\nIn order to construct such a query in SQLAlchemy, the query object must receive:\n\n\n1. A limit using `limit()`\n2. A `ZdbColumn` or `ZdbScore` using `order_by()`\n\nExample #1 - using a column marked as `ZdbColumn` (*Products.price*)\n\n```python\nq = q.filter(Products.author.in_([\"foo\", \"bar\"]))\nq = q.order_by(Products.price.desc(),\n Products.availability_date.desc()).limit(1).offset(1)\n```\n\n```sql\nSELECT [...] FROM products\n WHERE zdb('products', ctid) ==> '#limit(price desc, 1, 1) author:(\"foo\",\"bar\")'\nORDER BY products.price DESC, products.availability_date DESC\n```\n\nIn other words, if you were previously already using `limit()` in conjunction with `order_by()` in your query building and the subject column is of type `ZdbColumn`, it'll try to bake a proper query for it.\n\nExample #2 - using `ZdbScore`\n\n```python\nfrom sqlalchemy_zdb.types import ZdbScore\n\nq = q.filter(Products.author.in_([\"foo\", \"bar\"]))\nq = q.order_by(ZdbScore(\"asc\"),\n Products.availability_date.desc(),\n Products.long_description.desc())\nq = q.limit(1)\nq = q.offset(1)\n```\n\n```sql\nSELECT [...] FROM products\n WHERE zdb('products', ctid) ==> '#limit(_score asc, 1, 1) author:(\"foo\",\"bar\")'\nORDER BY zdb_score('products', ctid) ASC, products.availability_date DESC, products.long_description DESC\n```\n\nMore can be read about `#limit` in the [ZomboDB documentation](https://github.com/zombodb/zombodb/blob/master/SYNTAX.md#limitoffset-with-sorting).\n\n## Constructing filters\nIf you want to have more control over your query, you may use `zdb_raw_query` directly.\n\nPhrase query:\n\n from sqlalchemy_zdb import zdb_raw_query, ZdbPhrase\n\n session.query(Post.text)\\\n .filter(zdb_raw_query(Post.text == 'hey joe'))\n\n\n SELECT post.text AS post_text\n FROM post\n WHERE zdb('post', ctid) ==> 'text:\"hey joe\"'\n\nBoolean query:\n\n pg_session.query(Post.text)\\\n .filter(zdb_raw_query(or_(Post.text == 'foo', and_(Post.text == 'bar', Post.text == 'fuzz'))))\n\n SELECT post.text AS post_text\n FROM post\n WHERE zdb('post', ctid) ==> '(text:\"foo\" or (text:\"bar\" and text:\"fuzz\"))'\n\nmore\\_like\\_this:\n\n pg_session.query(Post.text)\\\n .filter(zdb_raw_query(Post.text.match('foo')))\n\n SELECT post.text AS post_text\n FROM post\n WHERE zdb('post', ctid) ==> 'text:@foo'\n\nComparison operations:\n\n pg_session.query(Post.text)\\\n .filter(zdb_raw_query(Post.comments > 1))\n\n SELECT post.text AS post_text\n FROM post\n WHERE zdb('post', ctid) ==> 'comments > 1'\n\nRaw query:\n\n pg_session.query(Post.text)\\\n .filter(zdb_raw_query(Post, 'text:(sports,box) or long_description:(wooden w/5 away) and comments < 10'))\n\n SELECT post.text AS post_text\n FROM post\n WHERE zdb('post', ctid) ==> 'text:(sports,box) or long_description:(wooden w/5 away) and comments < 10'\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/skftn/sqlalchemy_zdb/archive/master.zip", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/skftn/sqlalchemy_zdb", "keywords": "sqlalchemy zombodb", "license": "", "maintainer": "", "maintainer_email": "", "name": "sqlalchemy-zdb", "package_url": "https://pypi.org/project/sqlalchemy-zdb/", "platform": "", "project_url": "https://pypi.org/project/sqlalchemy-zdb/", "project_urls": { "Download": "https://github.com/skftn/sqlalchemy_zdb/archive/master.zip", "Homepage": "https://github.com/skftn/sqlalchemy_zdb" }, "release_url": "https://pypi.org/project/sqlalchemy-zdb/0.1.3/", "requires_dist": [ "psycopg2", "sqlalchemy (>=1.1.6)", "sqlalchemy-utils" ], "requires_python": "", "summary": "SQLAlchemy support for ZomboDB", "version": "0.1.3" }, "last_serial": 3307440, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "0920471a6cceefedaffccf71c3027d4f", "sha256": "4e4962dd43ca19580c90c49eff354b7b6b0a3dbf65d3bde87626e44020f595f0" }, "downloads": -1, "filename": "sqlalchemy_zdb-0.1.0-py2-none-any.whl", "has_sig": false, "md5_digest": "0920471a6cceefedaffccf71c3027d4f", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 12472, "upload_time": "2017-05-16T22:05:54", "url": "https://files.pythonhosted.org/packages/f5/8f/0ea1877024c249f89fe7df395102370973241773efd22938e9fd64ffe394/sqlalchemy_zdb-0.1.0-py2-none-any.whl" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "82e0e0fa2f0844f45573586159c5156d", "sha256": "199364cb1f89773fac80966da985ba5b97f47616c9bc7ff163c65788553bbd43" }, "downloads": -1, "filename": "sqlalchemy_zdb-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "82e0e0fa2f0844f45573586159c5156d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13226, "upload_time": "2017-05-20T17:34:37", "url": "https://files.pythonhosted.org/packages/e8/45/a4f736c1b59cf4482ed09fd38f949c4a0a658a586e53200c68d0ce3af558/sqlalchemy_zdb-0.1.1-py3-none-any.whl" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "59091c033f9a843ec07153a5620c4a54", "sha256": "77446ac876eef7e1d0f348c4b2f2001f3aab8b15f6ca95a3ca283131f740dfec" }, "downloads": -1, "filename": "sqlalchemy_zdb-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "59091c033f9a843ec07153a5620c4a54", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13296, "upload_time": "2017-05-21T17:24:01", "url": "https://files.pythonhosted.org/packages/c1/2a/cdf99d874cd181f07c4fc3829884ba41d5333a70ab5f35016cbdbe5d406c/sqlalchemy_zdb-0.1.2-py3-none-any.whl" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "b9ef2a3edbee18538b653051bad1a950", "sha256": "b2c24289ecc7aba4a5188cdbc91be4f72dfd2c3825427dfa4df786dc99c6d657" }, "downloads": -1, "filename": "sqlalchemy_zdb-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "b9ef2a3edbee18538b653051bad1a950", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15841, "upload_time": "2017-11-05T17:59:33", "url": "https://files.pythonhosted.org/packages/a1/c6/d35868088c52b9bc720f3de950a753bf6a8a9d9846415cb230630e89ec62/sqlalchemy_zdb-0.1.3-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b9ef2a3edbee18538b653051bad1a950", "sha256": "b2c24289ecc7aba4a5188cdbc91be4f72dfd2c3825427dfa4df786dc99c6d657" }, "downloads": -1, "filename": "sqlalchemy_zdb-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "b9ef2a3edbee18538b653051bad1a950", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15841, "upload_time": "2017-11-05T17:59:33", "url": "https://files.pythonhosted.org/packages/a1/c6/d35868088c52b9bc720f3de950a753bf6a8a9d9846415cb230630e89ec62/sqlalchemy_zdb-0.1.3-py3-none-any.whl" } ] }