검색
Aeca는 검색을 위한 많은 연산자가 준비되어 있고 이를 이용하여 검색하는 방법에 대해서 설명합니다. 여기서는 그 중 점수화하지 않고 일치/불일치 여부만 판단하는 필터 검색에 대한 내용을 다루고 있습니다. 이러한 필터 검색은 주로 정형 데이터 검색에 적합합니다.
만약 단어의 일부, 벡터 검색 등을 원하신다면 전문 검색을 참고해 주세요.
사전 준비
검색을 위한 데이터를 입력하는 과정을 설명합니다. 예제로 Kaggle (opens in a new tab)에 공개된 Car information dataset (opens in a new tab)을 사용합니다.
이 데이터셋의 다음과 같은 필드를 가지고 있습니다.
name
: Unique identifier for each automobile.mpg
: Fuel efficiency measured in miles per gallon.cylinders
: Number of cylinders in the engine.displacement
: Engine displacement, indicating its size or capacity.horsepower
: Power output of the engine.weight
: Weight of the automobile.acceleration
: Capability to increase speed, measured in seconds.model_year
: Year of manufacture for the automobile model.origin
: Country or region of origin for each automobile.
이제 예제 데이터를 가져옵니다.
import pandas as pd
df = pd.read_csv("automobile.csv")
df = df.reset_index()
df = df.rename(columns={"index": "doc_id"})
print(df.head(3))
실행 결과는 다음과 같습니다.
doc_id name mpg cylinders displacement \
0 0 chevrolet chevelle malibu 18.0 8 307.0
1 1 buick skylark 320 15.0 8 350.0
2 2 plymouth satellite 18.0 8 318.0
horsepower weight acceleration model_year origin
0 130.0 3504 12.0 70 usa
1 165.0 3693 11.5 70 usa
2 150.0 3436 11.0 70 usa
그리고 데이터 타입을 확인해 보면
print(df.dtypes)
적절한 데이터 타입을 가지고 있는 것을 확인할 수 있습니다. 검색 과정에 영향을 받기 때문에 데이터 삽입 전 의도에 맞는 데이터 타입을 가지고 있는지 확인하는 것이 좋습니다.
doc_id int64
name object
mpg float64
cylinders int64
displacement float64
horsepower float64
weight int64
acceleration float64
model_year int64
origin object
dtype: object
이어서 데이터 입력과 관리에서 설명한 내용과 같이 컬렉션을 생성하고 데이터를 입력합니다.
from aeca import DocumentDB
doc_db = DocumentDB(channel)
indexes = [
{
"index_type": "kPrimaryKey",
"fields": ["doc_id"]
}
]
collection_name = "car_info"
doc_db.create_collection(collection_name, indexes=indexes)
doc_db.insert(collection_name, df.to_dict(orient="records"))
df = doc_db.find(collection_name, {"$limit": 10})
print(df.head(3))
print(df.dtypes)
예제를 단순화 하기 위해서 색인 정의는 제외되어 있습니다. 빠른 검색을 위해서 색인 정의를 위한 스키마를 참고하여 색인을 생성할 수 있습니다.
입력된 데이터는 아래와 같이 확인할 수 있습니다.
acceleration cylinders displacement doc_id horsepower model_year \
0 12.0 8 307.0 0 130.0 70
1 11.5 8 350.0 1 165.0 70
2 11.0 8 318.0 2 150.0 70
mpg name origin weight
0 18.0 chevrolet chevelle malibu usa 3504
1 15.0 buick skylark 320 usa 3693
2 18.0 plymouth satellite usa 3436
acceleration float64
cylinders Int32
displacement float64
doc_id Int32
horsepower float64
model_year Int32
mpg float64
name string[python]
origin string[python]
weight Int32
dtype: object
쿼리 작성
사전 준비를 통해 입력된 데이터에서 cylinders
가 6개이고 horsepower
가 100마력 이상인 자동차를 찾아보도록 하겠습니다. 그리고 name
, horsepower
, cylinders
, model_year
를 출력하고 마력을 기준으로 내림차순 정렬을 하고자 합니다.
이 조건은 다음과 같이 표현할 수 있습니다.
columns = [
"name",
"horsepower",
"cylinders",
"model_year"
]
query = [
{
"cylinders": 6,
"horsepower": {
"$ge": 100
},
"$project": columns,
"$sort": [{"horsepower": "desc"}]
}
]
df = doc_db.find(collection_name, query, columns=columns)
print(df.head(10))
실행 결과는 다음과 같습니다.
name horsepower cylinders model_year
0 buick regal sport coupe (turbo) 165.0 6 78
1 peugeot 604sl 133.0 6 78
2 datsun 280-zx 132.0 6 80
3 volvo 264gl 125.0 6 78
4 toyota mark ii 122.0 6 73
5 mercedes-benz 280s 120.0 6 76
6 datsun 810 maxima 120.0 6 81
7 amc concord d/l 120.0 6 78
8 toyota cressida 116.0 6 81
9 chevrolet citation 115.0 6 79
쿼리 조건을 하나씩 살펴보면, 아래 조건은 cylinders
가 6인 항목을 찾습니다.
"cylinders": 6
이는 비교 연산이며 아래의 쿼리와 의미상 같습니다.
"cylinders": {"$eq": 6}
이어서 다음 조건은 horsepower
가 100보다 크거나 같은 값을 찾고 있습니다.
"horsepower": {
"$ge": 100
}
다음과 같이 $project
를 연산자를 사용하여 columns
에서 정의한 칼럼만 가져오도록 설정했습니다.
"$project": columns
이어서 $sort
연산자를 사용하여 선택된 결과를 내림차순(desc
) 정렬합니다.
"$sort": [{"horsepower": "desc"}]
마지막으로 DocumentDB.find 함수를 사용하여 검색을 요청합니다.
df = doc_db.find(collection_name, query, columns=columns)
파이프라인
위의 검색 결과에서 model_year
가 80년 이후로 생산된 자동차를 검색하도록 수정하겠습니다. 물론 기존 쿼리를 수정하여 원하는 결과를 얻을 수 있지만 여기서는 Aeca에서 지원하는 쿼리 파이프라인을 사용합니다.
아래의 코드와 같이 기존 쿼리에 쿼리를 추가했습니다.
query = [
{
"cylinders": 6,
"horsepower": {
"$ge": 100
},
"$project": columns,
"$sort": [{"horsepower": "desc"}]
},
{
"model_year": {
"$ge": 80
}
}
]
df = doc_db.find(collection_name, query, columns=columns)
print(df)
실행 결과는 의도와 같이 출력되는 것을 확인할 수 있습니다.
name horsepower cylinders model_year
0 datsun 280-zx 132.0 6 80
1 datsun 810 maxima 120.0 6 81
2 toyota cressida 116.0 6 81
3 ford granada l 112.0 6 82
4 chevrolet citation 110.0 6 81
5 buick century 110.0 6 81
6 buick century limited 110.0 6 82
파이프라인은 다음과 같이 동작합니다.
- 입력된 쿼리를 순서대로 실행
- 쿼리는 이전 검색 결과를 기반으로 실행
위와 같은 특성이 있기 때문에 만약 파이프라인의 첫번째 쿼리에서 "$project": ["name", "horsepower", "cylinders"]
로 전달하여 model_year
가 이전 쿼리 검색 결과에 없었다면 위의 쿼리는 실행되지 않습니다.
첫번째 파이프에 대해서만 색인을 참조하며 두번째 이후의 파이프는 필터로써 동작합니다.
연산자
Aeca는 검색을 위한 다양한 기능을 제공하고 있습니다. 자세한 내용은 연산자 문서를 참고해 주세요.