Merge branch 'testing' into feature/#135-trade-without-to
This commit is contained in:
commit
4afa21d7d7
|
@ -6,15 +6,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
ml).
|
||||
|
||||
## master
|
||||
[1.0.4-beta]
|
||||
[1.0.5-beta]
|
||||
|
||||
## testing
|
||||
[1.0.5-beta]
|
||||
[1.0.6-beta]
|
||||
|
||||
## [1.0.6-beta]
|
||||
|
||||
## [1.0.5-beta]
|
||||
- [addend] #124 adding endpoint for extract the internal stats of use
|
||||
- [addend] #122 system for verify all documents that it's produced from devicehub
|
||||
- [addend] #127 add one code for every named tag
|
||||
- [addend] #131 add one code for every device
|
||||
- [bugfix] #138 search device with devicehubId
|
||||
|
||||
## [1.0.4-beta]
|
||||
- [addend] #95 adding endpoint for check the hash of one report
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = "1.0.5-beta"
|
||||
__version__ = "1.0.6-beta"
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
"""add code device search
|
||||
|
||||
Revision ID: 8d34480c82c4
|
||||
Revises: 8cb91ad1cc40
|
||||
Create Date: 2021-04-26 12:00:36.635784
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
from alembic import context
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
from ereuse_devicehub.resources.device.search import DeviceSearch
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '8d34480c82c4'
|
||||
down_revision = '8cb91ad1cc40'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def get_inv():
|
||||
INV = context.get_x_argument(as_dictionary=True).get('inventory')
|
||||
if not INV:
|
||||
raise ValueError("Inventory value is not specified")
|
||||
return INV
|
||||
|
||||
def upgrade():
|
||||
op.add_column('device_search',
|
||||
sa.Column('devicehub_ids',
|
||||
postgresql.TSVECTOR(),
|
||||
nullable=True),
|
||||
schema=f'{get_inv()}')
|
||||
|
||||
op.create_index('devicehub_ids gist',
|
||||
'device_search',
|
||||
['devicehub_ids'],
|
||||
unique=False,
|
||||
postgresql_using='gist',
|
||||
schema=f'{get_inv()}')
|
||||
|
||||
# Next of the migration execute: dh inv search
|
||||
|
||||
def downgrade():
|
||||
op.drop_index('devicehub_ids gist',
|
||||
table_name='device_search',
|
||||
schema=f'{get_inv()}')
|
||||
op.drop_column('device_search', 'devicehub_ids', schema=f'{get_inv()}')
|
|
@ -26,12 +26,14 @@ class DeviceSearch(db.Model):
|
|||
|
||||
properties = db.Column(TSVECTOR, nullable=False)
|
||||
tags = db.Column(TSVECTOR)
|
||||
devicehub_ids = db.Column(TSVECTOR)
|
||||
|
||||
__table_args__ = (
|
||||
# todo to add concurrency this should be commited separately
|
||||
# see https://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#indexes-with-concurrently
|
||||
db.Index('properties gist', properties, postgresql_using='gist'),
|
||||
db.Index('tags gist', tags, postgresql_using='gist'),
|
||||
db.Index('devicehub_ids gist', devicehub_ids, postgresql_using='gist'),
|
||||
{
|
||||
'prefixes': ['UNLOGGED']
|
||||
# Only for temporal tables, can cause table to empty on turn on
|
||||
|
@ -140,10 +142,16 @@ class DeviceSearch(db.Model):
|
|||
)
|
||||
).filter(Tag.device_id == device.id).join(Tag.org)
|
||||
|
||||
devicehub_ids = session.query(
|
||||
search.Search.vectorize(
|
||||
(db.func.string_agg(Device.devicehub_id, ' '), search.Weight.A),
|
||||
)
|
||||
).filter(Device.devicehub_id == device.devicehub_id)
|
||||
|
||||
# Note that commit flushes later
|
||||
# todo see how to get rid of the one_or_none() by embedding those as subqueries
|
||||
# I don't like this but I want the 'on_conflict_on_update' thingie
|
||||
device_document = dict(properties=properties.one_or_none(), tags=tags.one_or_none())
|
||||
device_document = dict(properties=properties.one_or_none(), tags=tags.one_or_none(), devicehub_ids=devicehub_ids.one_or_none())
|
||||
insert = postgresql.insert(DeviceSearch.__table__) \
|
||||
.values(device_id=device.id, **device_document) \
|
||||
.on_conflict_do_update(constraint='device_search_pkey', set_=device_document)
|
||||
|
|
|
@ -54,6 +54,7 @@ class LotQ(query.Query):
|
|||
|
||||
class Filters(query.Query):
|
||||
id = query.Or(query.Equal(Device.id, fields.Integer()))
|
||||
devicehub_id = query.Or(query.ILike(Device.devicehub_id))
|
||||
type = query.Or(OfType(Device.type))
|
||||
model = query.ILike(Device.model)
|
||||
manufacturer = query.ILike(Device.manufacturer)
|
||||
|
@ -154,10 +155,15 @@ class DeviceView(View):
|
|||
if search_p:
|
||||
properties = DeviceSearch.properties
|
||||
tags = DeviceSearch.tags
|
||||
devicehub_ids = DeviceSearch.devicehub_ids
|
||||
query = query.join(DeviceSearch).filter(
|
||||
search.Search.match(properties, search_p) | search.Search.match(tags, search_p)
|
||||
search.Search.match(properties, search_p) |
|
||||
search.Search.match(tags, search_p) |
|
||||
search.Search.match(devicehub_ids, search_p)
|
||||
).order_by(
|
||||
search.Search.rank(properties, search_p) + search.Search.rank(tags, search_p)
|
||||
search.Search.rank(properties, search_p) +
|
||||
search.Search.rank(tags, search_p) +
|
||||
search.Search.rank(devicehub_ids, search_p)
|
||||
)
|
||||
return query.filter(*args['filter']).order_by(*args['sort'])
|
||||
|
||||
|
|
|
@ -248,6 +248,8 @@ def test_device_query_search(user: UserClient):
|
|||
assert i['items'][0]['id'] == 1
|
||||
i, _ = user.get(res=Device, query=[('search', 'intel')])
|
||||
assert len(i['items']) == 1
|
||||
i, _ = user.get(res=Device, query=[('search', i['items'][0]['devicehubID'])])
|
||||
assert len(i['items']) == 1
|
||||
i, _ = user.get(res=Device, query=[('search', '1')])
|
||||
assert len(i['items']) == 1
|
||||
|
||||
|
|
Reference in a new issue