You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
geodata-catalog/backend/src/crud.py

133 lines
5.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()