Skip to content

Commit

Permalink
add category point
Browse files Browse the repository at this point in the history
  • Loading branch information
bhnvx committed Feb 26, 2024
1 parent dc88949 commit 502e6d0
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 7 deletions.
4 changes: 2 additions & 2 deletions app/dtos/category/category_response.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import dataclasses
from typing import Sequence

from app.entities.category.category_codes import CategoryCode
from app.entities.category.categories import Category


@dataclasses.dataclass
class CategoryResponse:
categories: Sequence[CategoryCode]
categories: Sequence[Category]
63 changes: 63 additions & 0 deletions app/entities/category/categories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import dataclasses

from app.entities.category.category_codes import CategoryCode


@dataclasses.dataclass
class Category:
code: str
name: str
image_url: str
deep_link: str


CATEGORIES: dict[CategoryCode, Category] = {
CategoryCode.CHICKEN: Category(
code=CategoryCode.CHICKEN,
name="치킨",
image_url="https://chicken.png",
deep_link="app://chicken_action",
),
CategoryCode.BURGER: Category(
code=CategoryCode.BURGER,
name="버거",
image_url="https://burger.png",
deep_link="app://burger_action",
),
CategoryCode.PIZZA: Category(
code=CategoryCode.PIZZA,
name="피자",
image_url="https://pizza.png",
deep_link="app://pizza_action",
),
CategoryCode.SANDWICH: Category(
code=CategoryCode.SANDWICH,
name="샌드위치",
image_url="https://sandwich.png",
deep_link="app://sandwich_action",
),
CategoryCode.KOREAN: Category(
code=CategoryCode.KOREAN,
name="한식",
image_url="https://korean.png",
deep_link="app://korean_action",
),
CategoryCode.JAPANESE: Category(
code=CategoryCode.JAPANESE,
name="일식",
image_url="https://japanese.png",
deep_link="app://japanese_action",
),
CategoryCode.SALAD: Category(
code=CategoryCode.SALAD,
name="샐러드",
image_url="https://salad.png",
deep_link="app://salad_action",
),
CategoryCode.CAFE: Category(
code=CategoryCode.CAFE,
name="카페",
image_url="https://cafe.png",
deep_link="app://cafe_action",
),
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from dataclasses import asdict

import pymongo
from motor.motor_asyncio import AsyncIOMotorCollection
from pymongo import ReturnDocument
from pymongo.errors import DuplicateKeyError

from app.entities.category.category_codes import CategoryCode
from app.entities.collections.category_point.category_point_document import (
CategoryPointDocument,
)
from app.entities.collections.geo_json import GeoJsonPoint
from app.utils.mongo import db


class CategoryPointCollection:
_collection = AsyncIOMotorCollection(db, "category_points")

@classmethod
async def set_index(cls) -> None:
await cls._collection.create_index(
[
("point", pymongo.GEOSPHERE),
("codes", pymongo.ASCENDING),
]
)
await cls._collection.create_index("cache_key", unique=True)

@classmethod
async def insert_or_replace(
cls, cache_key: str, point: GeoJsonPoint, codes: tuple[CategoryCode, ...]
) -> CategoryPointDocument:
document_to_insert = {
"cache_key": cache_key,
"codes": codes,
"point": asdict(point),
}
try:
result = await cls._collection.insert_one(document_to_insert)
_id = result.inserted_id
except DuplicateKeyError:
inserted_document = await cls._collection.find_one_and_replace(
{"cache_key": cache_key},
document_to_insert,
return_document=ReturnDocument.AFTER,
)
_id = inserted_document["_id"]
return CategoryPointDocument(
codes=codes,
point=point,
cache_key=cache_key,
_id=_id,
)
12 changes: 12 additions & 0 deletions app/entities/collections/category_point/category_point_document.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import dataclasses

from app.entities.category.category_codes import CategoryCode
from app.entities.collections.base_document import BaseDocument
from app.entities.collections.geo_json import GeoJsonPoint


@dataclasses.dataclass
class CategoryPointDocument(BaseDocument):
cache_key: str
codes: tuple[CategoryCode, ...]
point: GeoJsonPoint
9 changes: 5 additions & 4 deletions app/services/category_service.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import asyncio

from app.entities.category.categories import CATEGORIES, Category
from app.entities.category.category_codes import CategoryCode
from app.entities.collections.geo_json import GeoJsonPoint
from app.entities.collections.shop.shop_collection import ShopCollection


async def get_distinct_home_categories(longitude: float, latitude: float) -> tuple[CategoryCode, ...]:
async def get_distinct_home_categories(longitude: float, latitude: float) -> tuple[Category, ...]:
return tuple(
code
CATEGORIES[code]
for code in await ShopCollection.get_distinct_category_codes_by_point_intersects(
GeoJsonPoint(coordinates=[longitude, latitude])
)
)


async def get_home_categories_one_by_one(longitude: float, latitude: float) -> tuple[CategoryCode, ...]:
async def get_home_categories_one_by_one(longitude: float, latitude: float) -> tuple[Category, ...]:
li = [
ShopCollection.exists_by_category_and_point_intersects(code, GeoJsonPoint(coordinates=[longitude, latitude]))
for code in CategoryCode
]
return tuple(code for code, exists in zip(CategoryCode, await asyncio.gather(*li)) if exists)
return tuple(CATEGORIES[code] for code, exists in zip(CategoryCode, await asyncio.gather(*li)) if exists)
2 changes: 1 addition & 1 deletion app/tests/apis/category/v1/test_home_category_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async def test_api_get_categories_distinct() -> None:

# Then
assert response.status_code == status.HTTP_200_OK
assert [elem for elem in response.json()["categories"]] == [CategoryCode.CHICKEN.value]
assert [elem["code"] for elem in response.json()["categories"]] == [CategoryCode.CHICKEN.value]


async def test_api_get_categories_one_by_one_latitude_too_big() -> None:
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from app.entities.category.category_codes import CategoryCode
from app.entities.collections.category_point.category_point_collection import (
CategoryPointCollection,
)
from app.entities.collections.geo_json import GeoJsonPoint


async def test_insert_or_replace() -> None:
# Given
cache_key = "1_1"
point = GeoJsonPoint(coordinates=[1, 1])
codes = (CategoryCode.CHICKEN, CategoryCode.PIZZA)

# When
category_point = await CategoryPointCollection.insert_or_replace(cache_key, point, codes)
category_point_upserted = await CategoryPointCollection.insert_or_replace(cache_key, point, codes)

# Then
result = await CategoryPointCollection._collection.find_one({"_id": category_point.id})
assert category_point.cache_key == result["cache_key"]
assert category_point.point.coordinates == result["point"]["coordinates"]
assert category_point.codes == tuple(CategoryCode(code) for code in result["codes"])
assert category_point_upserted.cache_key == result["cache_key"]
assert category_point_upserted.point.coordinates == result["point"]["coordinates"]
assert category_point_upserted.codes == tuple(CategoryCode(code) for code in result["codes"])

0 comments on commit 502e6d0

Please sign in to comment.