Elasticsearch와 Django ORM에서의 핵심 기능
Elasticsearch(ES)와 Django ORM에서 A, Q, F는 쿼리 구축과 조작을 위한 핵심 도구입니다:
A(Aggregation): 데이터 집계 연산(통계, 그룹화 등) 처리Q(Query): 복잡한 조건 구성(AND, OR, NOT 논리 연산)F(Field): 데이터베이스 필드 간 연산(계산, 비교 등)
1. Elasticsearch의 A와 Q
1.1 Q 객체: 복합 쿼리
논리 연산자를 활용한 검색 조건 조합:
from elasticsearch_dsl import Q
from blog.documents import PostDocument
# 제목이 "Elasticsearch"이고 조회수가 100 초과인 문서 검색
search_query = Q("match", title="Elasticsearch") & Q("range", view_count={"gt": 100})
results = PostDocument.search().query(search_query).execute()
ES 쿼리 변환:
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Elasticsearch" } },
{ "range": { "view_count": { "gt": 100 } } }
]
}
}
}
1.2 A 객체: 집계 처리
카테고리별 문서 수 집계 예시:
from elasticsearch_dsl import A
category_agg = A("terms", field="category")
search = PostDocument.search().aggs.bucket("category_count", category_agg)
response = search.execute()
for bucket in response.aggregations.category_count.buckets:
print(f"카테고리: {bucket.key}, 개수: {bucket.doc_count}")
ES 쿼리 변환:
{
"aggs": {
"category_count": {
"terms": { "field": "category" }
}
}
}
2. Django ORM의 Q와 F
2.1 Q 객체: 고급 필터링
논리 연산을 통한 조건 결합:
from django.db.models import Q
from shop.models import Product
# 상품명이 'Django' 또는 가격이 10000원 미만
products = Product.objects.filter(Q(name="Django") | Q(price__lt=10000))
SQL 변환:
SELECT * FROM product WHERE name = 'Django' OR price < 10000;
2.2 F 객체: 필드 연산
데이터베이스 수준에서의 필드 비교:
from django.db.models import F
# 재고량이 최소 재고 수준보다 많은 상품
products = Product.objects.filter(stock__gt=F("min_stock"))
SQL 변환:
SELECT * FROM product WHERE stock > min_stock;
2.2.1 수치 연산 예시
# 모든 상품 가격 10% 인상
Product.objects.update(price=F("price") * 1.1)
SQL 변환:
UPDATE product SET price = price * 1.1;
3. Q와 F의 조합
복합 조건과 필드 연산 통합:
# 재고 > 최소재고 또는 이름이 '특별상품'인 경우
products = Product.objects.filter(
Q(stock__gt=F("min_stock")) | Q(name="특별상품")
)
SQL 변환:
SELECT * FROM product WHERE stock > min_stock OR name = '특별상품';
4. 기술 비교
| 기능 | Elasticsearch DSL | Django ORM |
|---|---|---|
| 기본 쿼리 | Q("match", field=value) | Q(field=value) |
| 범위 쿼리 | Q("range", field={"gte": value}) | filter(field__gte=value) |
| 논리 연산 | Q(A) & Q(B) | Q(A) | Q(B) |
| 필드 연산 | 스크립트 처리 | F("field1") * F("field2") |
| 집계 | A("terms", field="category") | annotate(Count("field")) |