|
3 | 3 | import asyncio |
4 | 4 | import logging |
5 | 5 | from base64 import urlsafe_b64decode, urlsafe_b64encode |
| 6 | +from collections.abc import Iterable |
6 | 7 | from copy import deepcopy |
7 | | -from typing import Any, Dict, Iterable, List, Optional, Tuple, Type |
| 8 | +from typing import Any, Dict, List, Optional, Tuple, Type |
8 | 9 |
|
9 | 10 | import attr |
10 | 11 | import orjson |
11 | 12 | from fastapi import HTTPException |
12 | 13 | from opensearchpy import exceptions, helpers |
13 | 14 | from opensearchpy.helpers.query import Q |
14 | 15 | from opensearchpy.helpers.search import Search |
15 | | -from starlette.requests import Request |
16 | | - |
17 | 16 | from stac_fastapi.core.base_database_logic import BaseDatabaseLogic |
18 | 17 | from stac_fastapi.core.serializers import CollectionSerializer, ItemSerializer |
19 | 18 | from stac_fastapi.core.utilities import MAX_LIMIT, bbox2polygon |
|
26 | 25 | AsyncOpensearchSettings as AsyncSearchSettings, |
27 | 26 | ) |
28 | 27 | from stac_fastapi.opensearch.config import OpensearchSettings as SyncSearchSettings |
29 | | -from stac_fastapi.sfeos_helpers import filter as filter_module |
30 | 28 | from stac_fastapi.sfeos_helpers.database import ( |
31 | 29 | apply_free_text_filter_shared, |
32 | 30 | apply_intersects_filter_shared, |
|
66 | 64 | from stac_fastapi.types.errors import ConflictError, NotFoundError |
67 | 65 | from stac_fastapi.types.links import resolve_links |
68 | 66 | from stac_fastapi.types.stac import Collection, Item |
| 67 | +from starlette.requests import Request |
| 68 | + |
| 69 | +from stac_fastapi.sfeos_helpers import filter as filter_module |
69 | 70 |
|
70 | 71 | logger = logging.getLogger(__name__) |
71 | 72 |
|
@@ -387,19 +388,17 @@ def apply_bbox_filter(search: Search, bbox: List): |
387 | 388 | a geo_shape filter is added to the search object, set to intersect with the specified polygon. |
388 | 389 | """ |
389 | 390 | return search.filter( |
390 | | - Q( |
391 | | - { |
392 | | - "geo_shape": { |
393 | | - "geometry": { |
394 | | - "shape": { |
395 | | - "type": "polygon", |
396 | | - "coordinates": bbox2polygon(*bbox), |
397 | | - }, |
398 | | - "relation": "intersects", |
399 | | - } |
| 391 | + Q({ |
| 392 | + "geo_shape": { |
| 393 | + "geometry": { |
| 394 | + "shape": { |
| 395 | + "type": "polygon", |
| 396 | + "coordinates": bbox2polygon(*bbox), |
| 397 | + }, |
| 398 | + "relation": "intersects", |
400 | 399 | } |
401 | 400 | } |
402 | | - ) |
| 401 | + }) |
403 | 402 | ) |
404 | 403 |
|
405 | 404 | @staticmethod |
@@ -679,14 +678,21 @@ async def async_prep_create_item( |
679 | 678 |
|
680 | 679 | """ |
681 | 680 | await self.check_collection_exists(collection_id=item["collection"]) |
| 681 | + alias = index_alias_by_collection_id(item["collection"]) |
| 682 | + doc_id = mk_item_id(item["id"], item["collection"]) |
682 | 683 |
|
683 | | - if not exist_ok and await self.client.exists( |
684 | | - index=index_alias_by_collection_id(item["collection"]), |
685 | | - id=mk_item_id(item["id"], item["collection"]), |
686 | | - ): |
687 | | - raise ConflictError( |
688 | | - f"Item {item['id']} in collection {item['collection']} already exists" |
689 | | - ) |
| 684 | + if not exist_ok: |
| 685 | + alias_exists = await self.client.indices.exists_alias(name=alias) |
| 686 | + |
| 687 | + if alias_exists: |
| 688 | + alias_info = await self.client.indices.get_alias(name=alias) |
| 689 | + indices = list(alias_info.keys()) |
| 690 | + |
| 691 | + for index in indices: |
| 692 | + if await self.client.exists(index=index, id=doc_id): |
| 693 | + raise ConflictError( |
| 694 | + f"Item {item['id']} in collection {item['collection']} already exists" |
| 695 | + ) |
690 | 696 |
|
691 | 697 | return self.item_serializer.stac_to_db(item, base_url) |
692 | 698 |
|
@@ -903,7 +909,6 @@ async def json_patch_item( |
903 | 909 | "add", |
904 | 910 | "replace", |
905 | 911 | ]: |
906 | | - |
907 | 912 | if operation.path == "collection" and collection_id != operation.value: |
908 | 913 | await self.check_collection_exists(collection_id=operation.value) |
909 | 914 | new_collection_id = operation.value |
@@ -957,8 +962,8 @@ async def json_patch_item( |
957 | 962 | "script": { |
958 | 963 | "lang": "painless", |
959 | 964 | "source": ( |
960 | | - f"""ctx._id = ctx._id.replace('{collection_id}', '{new_collection_id}');""" # noqa: E702 |
961 | | - f"""ctx._source.collection = '{new_collection_id}';""" # noqa: E702 |
| 965 | + f"""ctx._id = ctx._id.replace('{collection_id}', '{new_collection_id}');""" |
| 966 | + f"""ctx._source.collection = '{new_collection_id}';""" |
962 | 967 | ), |
963 | 968 | }, |
964 | 969 | }, |
@@ -1180,7 +1185,7 @@ async def update_collection( |
1180 | 1185 | "source": {"index": f"{ITEMS_INDEX_PREFIX}{collection_id}"}, |
1181 | 1186 | "script": { |
1182 | 1187 | "lang": "painless", |
1183 | | - "source": f"""ctx._id = ctx._id.replace('{collection_id}', '{collection["id"]}'); ctx._source.collection = '{collection["id"]}' ;""", # noqa: E702 |
| 1188 | + "source": f"""ctx._id = ctx._id.replace('{collection_id}', '{collection["id"]}'); ctx._source.collection = '{collection["id"]}' ;""", |
1184 | 1189 | }, |
1185 | 1190 | }, |
1186 | 1191 | wait_for_completion=True, |
|
0 commit comments