연산자

여기서는 쿼리에서 사용 가능한 연산자를 설명합니다. 사용 가능한 연산자는 다음과 같습니다.

비교: $lt, $le, $gt, $ge, $eq, $ne

비교 연산자는 항목간 비교하거나 같거나 다른지를 판단합니다.

다음 예시는 key1 항목이 10보다 작은지를 검사합니다.

"key1": {
    "$lt": 10
}

포함: $in, $not_in

$in$not_in은 필드에 특정한 값들이 포함되는지 포함되지 않는지를 검사하는 연산자입니다.

다음 예시는 key1 항목에 1, 2, 5 중에 하나가 포함되어 있는지 검사합니다.

"key1": {
    "$in": [1, 2, 5]
}

존재 여부: $exists

필드에 값이 존재하는지 확인합니다.

다음 예시는 key1에 값이 존재 여부를 확인합니다.

"key1": {
    "$exists": True
}

부분 일치: $match

와일드카드(wildcard)를 사용하여 일치 여부를 확인합니다.

다음 예시는 key1search로 시작하는 문자열이 있는지 확인합니다. $optionsignore-case를 전달하면 대소문자 구별없이 확인할 수 있습니다.

"key1": {
    "$match": "search*",
    "$options": "ignore-case"
}

정규식 일치: $regex

정규식 (opens in a new tab)을 사용하여 일치 여부를 확인합니다.

다음은 key1에 숫자가 포함된 문자열을 찾는 예시입니다.

"key1": {
    "$regex": ".+\d+",
}

Boolean: $and, $or, $nor, $not

불리언 연산자를 통해 조건을 조합하여 검색할 수 있습니다.

아래는 id가 1, 2, 5 중에 하나이면서 titlesearch가 일치하지 않는 데이터를 찾는 쿼리의 예시입니다.

"$and": [
    {
        "id": {
            "$in": [1, 2, 5]
        }
    },
    {
        "$not": [
            {
                "title": {
                    "$match": "search*"
                }
            }
        ]
    }
]

Project: $project

$project는 칼럼을 선택하는 연산자 입니다.

다음 예시는 key1, key2를 선택하는 예시입니다.

"$project": ["key1", "key2"]

갯수 제한: $limit

$limit는 연산된 결과값에서 선택할 행의 수를 제한하는 연산자입니다.

다음 예시는 10개의 행을 선택하는 예시입니다.

"$limit": 10

시작 위치: $skip

$skip는 연산된 결과값에서 시작할 위치를 제한하는 연산자입니다.

다음 예시는 5번째 행부터 선택하는 예시입니다.

"$skip": 5

$skip$limit를 사용하여 pagenation을 구현할 수 있습니다.

정렬: $sort

$sort는 연산된 결과값을 정렬하는 연산자입니다.

다음 예시는 key1은 오름차순, key2를 내림차순으로 결과값을 정렬하는 예시입니다. 나열된 순서를 우선하여 정렬됩니다.

"$sort": [
    "key1",
    {"key2": "desc"},
]

Flatten: $unnest

$unnest는 지정된 칼럼의 데이터를 1차원 배열로 변환하는 연산자입니다.

예를 들어 다음과 같이 데이터가 있고

{
    "_meta": {
        "doc_id": 1
        "score": 0.9
    },
    "title": "example 1"
}

이 데이터를 다음과 같이 쿼리하면

"$unnest": "_meta"

다음과 같이 변환됩니다.

[
    "_meta.doc_id": 1,
    "_meta.score": 0.9,
    "title": "example 1"
]

값 지정: $literal

특정한 값을 칼럼에 추가합니다.

다음과 같은 데이터가 있을 때

data = [
    {"doc_id": 1, "data": 1},
    {"doc_id": 2, "data": 2},
    {"doc_id": 3, "data": 3},
]

다음과 같이 실행하면

query = {
    "$literal": {
        "text": "test"
    }
}

다음과 같은 결과를 얻을 수 있습니다.

실행 결과
   doc_id  data  text
0       1     1  test
1       2     2  test
2       3     3  test

통합: $group

$group 쿼리된 결과값을 통합하여 재가공하는 연산자입니다.

여기서는 검색에서 사용하는 예시를 다시 사용하겠습니다. 우리는 6기통인 모델의 연도별 모델 수와 모델명, 해당연도 마력의 최대값을 구해보고자 합니다. 이 쿼리는 다음과 같이 작성할 수 있습니다.

query = [
    {
        "cylinders": 6,
    },
    {
        "$group": {
            "_id": "model_year",
            "first_name": {
                "$first": "name"
            },
            "horsepower_max": {
                "$max": "horsepower"                
            },
            "count": {
                "$sum": 1
            }
        }
    }
]
df = doc_db.find(collection_name, query)
print(df)

하나씩 살펴보면, $group은 병합의 기준이 되는 칼럼인 _id를 필수적으로 입력 받습니다. 이 경우 연도별 병합이기 때문에 model_year를 선택했습니다.

"_id": "model_year"

다음 병합된 그룹에서 첫번째 모델의 name을 가져옵니다. 여기서 first_name$group으로 만들어질 결과물 칼럼의 이름입니다.

"first_name": {
    "$first": "name"
}

마지막 항목인 병합 결과물에 count라는 칼럼을 신규로 만들고 "$sum": 1 하여 model_year로 병합된 아이템들의 갯수를 계산합니다.

"count": {
    "$sum": 1
}

실행 결과는 다음과 같습니다.

실행 결과
    _id  count               first_name  horsepower_max
0    70      4          plymouth duster            97.0
1    71      8              amc gremlin           110.0
2    73      8         plymouth valiant           122.0
3    74      7          plymouth duster           110.0
4    75     12  plymouth valiant custom           110.0
5    76     10         plymouth valiant           120.0
6    77      5       chevrolet concours           110.0
7    78     12       pontiac phoenix lj           165.0
8    79      6        pontiac lemans v6           115.0
9    80      2              dodge aspen           132.0
10   81      7       chevrolet citation           120.0
11   82      3    buick century limited           112.0

$group의 연산자

병합에 사용할 수 있는 연산자는 다음과 같습니다.

Join: $join, $union

두개의 컬렉션을 병합합니다.

test.join.lefttest.join.right를 생성하고 예제 데이터를 삽입하도록 하겠습니다.

from aeca import DocumentDB
 
doc_db = DocumentDB(channel)
 
collection_names = ["test.join.left", "test.join.right"]
indexes = [
    {
        "index_type": "kPrimaryKey",
        "fields": ["doc_id"]
    }
]
data = {
    "test.join.left": [
        {"doc_id": 1, "left": 1},
        {"doc_id": 2, "left": 2},
        {"doc_id": 3, "left": 3},
    ],
    "test.join.right": [
        {"doc_id": 1, "right": 1},
        {"doc_id": 2, "right": 2},
        {"doc_id": 5, "right": 5},
    ]
}
 
for name in collection_names:
    doc_db.create_collection(name, indexes=indexes)
    doc_db.insert(name, data[name])

$join

다음은 test.join.lefttest.join.rightinner join 하는 예시입니다.

query = {
    "$join": {
        "type": "inner",
        "collection": "test.join.left",
        "query": {},
        "on": ["doc_id"]
    }
}
df = doc_db.find("test.join.right", query)
print(df)

$join에서 사용 가능한 옵션은 다음과 같습니다.

  • type: 조인 방법
    • inner: 내부 조인, 기본값
    • outer: 외부 조인
    • left: left 조인
    • right: right 조인
    • hash_inner: 해시 내부 조인
  • collection: 조인할 컬렉션
  • query: 조인할 컬렉션의 쿼리, 생략 가능
  • on: 조인할 키

위 예시의 실행 결과는 다음과 같습니다.

실행 결과
   doc_id  left  right
0       1     1      1
1       2     2      2

$union

다음은 test.join.lefttest.join.right$union 하는 예시입니다.

query = {
    "$union": {
        "type": "all",
        "collection": "test.join.left",
        "query": {},
        "on": ["doc_id"]
    }
}
df = doc_db.find("test.join.right", query)
print(df)

$join에서 사용 가능한 옵션은 다음과 같습니다.

  • type: 조인 방법
    • all: 전체
    • distinct: 중복 제거
  • collection: 조인할 컬렉션
  • query: 조인할 컬렉션의 쿼리, 생략 가능
  • on: 조인할 키

위 예시의 실행 결과는 다음과 같습니다.

실행 결과
   doc_id  left  right
0       1  <NA>      1
1       2  <NA>      2
2       5  <NA>      5
3       1     1   <NA>
4       2     2   <NA>
5       3     3   <NA>

색인 힌트: $hint

색인을 위한 힌트를 제공합니다. 컬렉션에는 하나 이상의 색인이 저장될 수 있고 입력된 쿼리에 대해 쿼리 플래너는 이 색인들을 조합하여 최적의 색인을 선택합니다. 그러나 $hint를 통해 색인이 선택되면 해당 색인을 우선적으로 사용합니다.

{
    "$search": {
        "query": "cat"
    },
    "$hint": "sk_fts"
}

전문 검색: $search

$search전문 검색하는 연산자입니다.

다음은 검색 예시입니다.

"$search": {
    "query": "content:(hello world)",
    "fields": ["content"]
}

사용 가능한 옵션은 다음과 같습니다.

항목설명타입기본값
query검색 쿼리
쿼리 작성 방법은 전문 검색를 참고
str
fields검색 대상 필드list[str]색인된 전체 필드
skip시작 위치int
limit후보수int
timeout만료 시간int
min_score최소 점수float
highlight하이라이트bool
default_operator+: Must
#: Filter
strNone: Should