|
|
from typing import List
|
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
from sqlalchemy.sql.expression import func
|
|
|
from sqlalchemy import inspect, text
|
|
|
|
|
|
from . import models, schemas
|
|
|
from .database import Base
|
|
|
|
|
|
|
|
|
def get_item(db: Session, item_id: int):
|
|
|
"""индивидуальные страницы для каждого Описания набора данных"""
|
|
|
return db.query(models.Item).filter(models.Item.id == item_id).first()
|
|
|
|
|
|
|
|
|
def get_item_by_description(db: Session, needle: str, skip: int = 0, limit: int = 20):
|
|
|
"""фильтры для поиска Описаний наборов данных по атрибутам
|
|
|
дополнительный возможный синтаксис в запросах преобразуется
|
|
|
в поисковый запрос содержащий:
|
|
|
- простой текст: переданные слова в любом порядке
|
|
|
- "текст в кавычках": переданные слова в указанном порядке
|
|
|
- OR: какие-либо из переданных слов
|
|
|
- -: не содержащий данного слова
|
|
|
"""
|
|
|
# hardcode russian for now
|
|
|
# built-in postgress websearch_to_tsquery() is good
|
|
|
# https://www.postgresql.org/docs/11/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
|
|
|
# TODO: add requested search columns [0]
|
|
|
items_table = inspect(models.Item).local_table
|
|
|
result = (
|
|
|
db.query(models.Item)
|
|
|
.filter(
|
|
|
items_table.c.geodata_search_ts.op("@@")(
|
|
|
func.websearch_to_tsquery('"russian"', needle)
|
|
|
)
|
|
|
)
|
|
|
.order_by(items_table.c.id)
|
|
|
.offset(skip)
|
|
|
.limit(limit)
|
|
|
.all()
|
|
|
)
|
|
|
return result
|
|
|
|
|
|
|
|
|
def get_item_by_detailed_description(
|
|
|
db: Session, query: schemas.DetailedSearchQuery, skip: int = 0, limit: int = 20
|
|
|
):
|
|
|
"""фильтры для поиска Описаний наборов данных по атрибутам
|
|
|
дополнительный возможный синтаксис основного запроса преобразуется
|
|
|
в поисковый запрос содержащий:
|
|
|
- простой текст: переданные слова в любом порядке
|
|
|
- "текст в кавычках": переданные слова в указанном порядке
|
|
|
- OR: какие-либо из переданных слов
|
|
|
- -: не содержащий данного слова
|
|
|
дополнительные поля ипользуются напрямую
|
|
|
"""
|
|
|
# hardcode russian for now
|
|
|
# built-in postgress websearch_to_tsquery() is good
|
|
|
# https://www.postgresql.org/docs/11/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
|
|
|
items_table = inspect(models.Item).local_table
|
|
|
result = db.query(models.Item)
|
|
|
|
|
|
# filter with the main query (if present)
|
|
|
if query.main_query is not None:
|
|
|
result = result.filter(
|
|
|
items_table.c.geodata_search_ts.op("@@")(
|
|
|
func.websearch_to_tsquery('"russian"', query.main_query)
|
|
|
)
|
|
|
)
|
|
|
# filter by additionalfields (if present)
|
|
|
result = result.filter_by(**query.dict(exclude={"main_query"}, exclude_none=True))
|
|
|
|
|
|
return result.order_by(items_table.c.id).offset(skip).limit(limit).all()
|
|
|
|
|
|
|
|
|
def get_items(db: Session, skip: int = 0, limit: int = 20):
|
|
|
"""список доступных в системе Описаний наборов данных"""
|
|
|
return db.query(models.Item).offset(skip).limit(limit).all()
|
|
|
|
|
|
|
|
|
def get_items_by_category(category: str, db: Session, skip: int = 0, limit: int = 20):
|
|
|
"""список доступных в категории Описаний наборов данных"""
|
|
|
return (
|
|
|
db.query(models.Item)
|
|
|
.filter(models.Item.category == category)
|
|
|
.offset(skip)
|
|
|
.limit(limit)
|
|
|
.all()
|
|
|
)
|
|
|
|
|
|
|
|
|
def insert_items(db: Session, items: List[schemas.ItemCreate]):
|
|
|
"""импорт в базу данных Описаний наборов данных"""
|
|
|
before = db.query(models.Item).count()
|
|
|
accepted = len(items)
|
|
|
# https://docs.sqlalchemy.org/en/14/dialects/postgresql.html#psycopg2-fast-execution-helpers
|
|
|
modeled_items = (models.ItemCreate(**item.dict()) for item in items)
|
|
|
db.add_all(modeled_items)
|
|
|
db.commit()
|
|
|
inserted = db.query(models.Item).count() - before
|
|
|
return (accepted, inserted)
|
|
|
|
|
|
|
|
|
def get_headers(db: Session):
|
|
|
"""полные заголовки таблиц"""
|
|
|
return db.query(models.Header).all()
|
|
|
|
|
|
|
|
|
def add_spacial_data(db: Session):
|
|
|
"""Превращает строковые данные с координатами, полученные из таблицы
|
|
|
в пространственные, и помещает их в отдельный столбец в общей базе данных
|
|
|
"""
|
|
|
check_t = text(
|
|
|
"""SELECT true
|
|
|
FROM pg_attribute
|
|
|
WHERE attrelid = 'geodata'::regclass
|
|
|
AND attname = 'geom'
|
|
|
AND NOT attisdropped
|
|
|
AND attnum > 0"""
|
|
|
)
|
|
|
create_t = text(
|
|
|
"""SELECT AddGeometryColumn( 'public', 'geodata', 'geom', 4326, 'POINT', 2 )"""
|
|
|
)
|
|
|
populate_t = text(
|
|
|
"""UPDATE geodata
|
|
|
SET geom = ST_SetSRID(ST_Point( y_coord::numeric, x_coord::numeric),4326)
|
|
|
"""
|
|
|
)
|
|
|
if not db.execute(check_t).all():
|
|
|
db.execute(create_t)
|
|
|
db.execute(populate_t)
|
|
|
db.commit()
|