fixing bug

This commit is contained in:
Cayo Puigdefabregas 2021-04-26 15:22:30 +02:00
parent e496f8009c
commit a65e4ffb82
3 changed files with 66 additions and 3 deletions

View file

@ -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()}')

View file

@ -26,12 +26,14 @@ class DeviceSearch(db.Model):
properties = db.Column(TSVECTOR, nullable=False) properties = db.Column(TSVECTOR, nullable=False)
tags = db.Column(TSVECTOR) tags = db.Column(TSVECTOR)
devicehub_ids = db.Column(TSVECTOR)
__table_args__ = ( __table_args__ = (
# todo to add concurrency this should be commited separately # todo to add concurrency this should be commited separately
# see https://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#indexes-with-concurrently # see https://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#indexes-with-concurrently
db.Index('properties gist', properties, postgresql_using='gist'), db.Index('properties gist', properties, postgresql_using='gist'),
db.Index('tags gist', tags, postgresql_using='gist'), db.Index('tags gist', tags, postgresql_using='gist'),
db.Index('devicehub_ids gist', devicehub_ids, postgresql_using='gist'),
{ {
'prefixes': ['UNLOGGED'] 'prefixes': ['UNLOGGED']
# Only for temporal tables, can cause table to empty on turn on # 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) ).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 # Note that commit flushes later
# todo see how to get rid of the one_or_none() by embedding those as subqueries # 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 # 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__) \ insert = postgresql.insert(DeviceSearch.__table__) \
.values(device_id=device.id, **device_document) \ .values(device_id=device.id, **device_document) \
.on_conflict_do_update(constraint='device_search_pkey', set_=device_document) .on_conflict_do_update(constraint='device_search_pkey', set_=device_document)

View file

@ -54,6 +54,7 @@ class LotQ(query.Query):
class Filters(query.Query): class Filters(query.Query):
id = query.Or(query.Equal(Device.id, fields.Integer())) id = query.Or(query.Equal(Device.id, fields.Integer()))
devicehub_id = query.Or(query.ILike(Device.devicehub_id))
type = query.Or(OfType(Device.type)) type = query.Or(OfType(Device.type))
model = query.ILike(Device.model) model = query.ILike(Device.model)
manufacturer = query.ILike(Device.manufacturer) manufacturer = query.ILike(Device.manufacturer)
@ -154,10 +155,15 @@ class DeviceView(View):
if search_p: if search_p:
properties = DeviceSearch.properties properties = DeviceSearch.properties
tags = DeviceSearch.tags tags = DeviceSearch.tags
devicehub_ids = DeviceSearch.devicehub_ids
query = query.join(DeviceSearch).filter( 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( ).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']) return query.filter(*args['filter']).order_by(*args['sort'])