정의 : 컴포넌트를 여러가지 파일로 분리하여 저장하고 JS가 아닌 JSX 라는 문법을 사용
- Webpack : 여러가지 분리된 파일 하나로 합쳐주는 라이브러리
- Babel : jsx를 비롯한 새로운 js 문법을 사용하기 위한 라이브러리
- Node.js : Webpack과 Babel 등 여러 라이브러리를 사용하기 위한 javascript 런타임
- Yarn : 캐싱 시스템 등 조금 더 개선된 npm(node package manager)
- Visual Studio Code : 실제 개발을 위해 필요한 에디터 (공짜)
컴포넌트 App.js 코드 분석
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
//파일에서 jsx문법 사용하려면 React 꼭 import
//Webpack을 사용하기에 logo.svg와 App.css를 이런식으로 불러옴
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
//컴포넌트 만드는 방법 중 하나인 클래스 이용하는 방법
//클래스는 꼭 render()이 있어야하고 그 내부에서 jsx를 반환
//return 뒤의 html 같은 코드 = jsx
export default App;
//작성된 컴포넌트를 다른 곳에서 불러 사용하게 할 수 있는 코드
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
//APP 컴포넌트 사용하기 위해 import
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
//브라우저 상 React컴포넌트를 보여주기 위해 ReacDOM.render(렌더링 결과물, 그릴 DOM ) 함수 사용
//public/index.html 파일에 있는 id가 'root'인 DOM을 찾아 app컴포넌트를 렌더링
serviceWorker.unregister();
from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class =
ViewSet
-> View(CRUD)를 설계하는 가장 간단한 방법
2. APIView
-> 장점 : 자신의 마음대로 코드를 작성할 수 있다.
-> 단점 : CBV의 장점인 중복되는 코드 제거를 하지 못한다.
-> Response : 클라이언트가 요청한 형태로 콘텐츠를 렌더링 해준다.
-> Status : Http 에서 제공하는 상태 코드는 숫자이지만, REST 프레임워크에서는 문자 형태의 식별자를 제공하여 상태를 좀더 잘 구분할 수 있도록 한다.
-> APIView를 상속해서 view를 설계할 때는 status 와 Response를 import 하여 Response과정을 작성
-> APIView를 상속해서 만든 CBV의 내부 함수들은 필요로 하는 HTTP Method 이름으로 갖는다.
-> 어떠한 status를 받고 response를 전달할지 직접 정하는 것이 apiview를 상속받은 cbv
class SnippetDetail(APIView):
def get(...):
...
def put(...):
...
def delete(...):
...
#SnippetDetail 클래스에 필요한 method는 GET, PUT, DELETE
##실습해보기
django-admin startproject <project-name>
cd <project-name>
python manage.py startapp <app-name>
settings.py에 App, rest_framework추가
models.py에 모델 작성 및 migrate
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
serializer.py 생성 및 작성
from .models import Post
from rest_framework import serializers
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = "__all__"
views.py 작성 1) 필요한 모듈 추가(apiview를 상속받은 cbv를 작성하기 위해 아래 모듈 추가)
from CBV.models import Post
from CBV.serializer import PostSerializer
from django.http import Http404
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
2)객체들 목록 가져오는 PostList 작성
- post 메서드는 다수의 post 객체를 반환하는 메서드
- 다수의 객체를 직렬화 하기위해서는 PostSerializer 에 many = True를 넘겨야 한다
- post 메서드는 새로운 객세 생성하는 함수
- 저장 성공시 상태코드 201(created) / 반환 실패시 400(bad request)반환
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views
urlpatterns = [
path("post", views.PostList.as_view()),
path("post/<int:pk>", views.PostDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
- 프로젝트 폴더 내부의 urls.py 에 include
from django.contrib import admin
from django.urls import path, include
import post.urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(post.urls)),
]
실행하고 http://127.0.0.1:8000/post 에 접속하면 정상 작동한다
4. Generic CBV
<분류>
기반 뷰(Base View): 뷰 클래스를 생성하고 다른, 제너릭 뷰의 부모 클래스가 되는 기본 제너릭 뷰
view : 최상위 부모 제너릭 뷰 클래스
TemplateView : 주어진 템플릿으로 렌더링
RedirectView : 주어진 URL로 리다이렉트
제너릭 보기 뷰(Generic Display View): 객체의 목록 또는 하나의 객체 상세 정보를 보여주는 뷰
DetailView : 조건에 맞는 하나의 객체 출력
ListView : 조건에 맞는 객체 목록 출력
제너릭 수정 뷰(Generic Edit View): 폼을 통해 객체를 생성, 수정, 삭제하는 기능을 제공하는 뷰
FormView : 폼이 주어지면 해당 폼 출력
CreateView : 객체 생성하는 폼 출력
UpdateView : 기존 객체 수정하는 폼 출력
DeleteView : 기존 객체 삭제하는 폼 출력
제너릭 날짜 뷰(Generic Date View): 날짜 기반 객체의 연/월/일 페이지로 구분해 보여주는 뷰
YearArchiveView : 주어진 연도에 해당하는 객체 출력
MonthArchiveView : 주어진 월에 해당하는 객체 출력
DayArchiveView : 주어진 날짜에 해당하는 객체 출력
TodayArchiveVIew : 오늘 날짜에 해당하는 객체 출력
DateDetailView : 주어진 연, 월, 일 PK(OR 슬러그)에 해당하는 객체 출력
<제너릭 뷰 오버라이딩>
속성 변수 오버라이딩
model : 기본 뷰(View, Template, RedirectView) 3개를 제외하고 모든 제너릭 뷰에서 사용한다.
queryset : 기본 뷰(View, Template, RedirectView) 3개를 제외하고 모든 제너릭 뷰에서 사용한다.queryset을 사용하면model속성은 무시된다.
template_name : TemplateView를 포함한 모든 제너릭 뷰에서 사용한다. 템플릿 파일명을 문자열로 지정한다.
context_object_name : 뷰에서 템플릿 파일에 전달하는 컨텍스트 변수명을 지정한다.
paginate_by : ListView와 날짜 기반 뷰(예, YearArchiveView)에서 사용한다. 페이징 기능이 활성화 된 경우 페이지당 출력 항목 수를 정수로 지정한다.
date_field : 날짜 기반 뷰(예, YearArchiveView)에서 사용한다. 이 필드의 타입은 DateField 또는 DateTimeField이다.
form_class : FormView, CreateView, UpdateView에서 폼을 만드는데 사용할 클래스를 지정한다.
success_url : FormView, CreateView, UpdateView, DeleteView에서 폼에 대한 처리가 성공한 후 리디이렉트할 URL 주소이다.
메소드 오버라이딩
def get_queryset() : 기본 뷰(View, Template, RedirectView) 3개를 제외하고 모든 제너릭 뷰에서 사용한다. 디폴트는queryset속성을 반환한다.queryset속성이 지정되지 않은 경우 모델 매니저 클래스의 all() 메소드를 호출해 QuerySet 객체를 생성해 반환한다.
def get_context_data(**kwargs) : 뷰에서 템플릿 파일에 넘겨주는 컨텍스트 데이터를 추가하거나 변경하는 목적으로 오버라이딩한다.
def form_valid(form)
<모델을 지정하는 방법 3가지>
model 속성 변수 지정
queryset 속성 변수 지정
def get_queryset() 메소드 오버라이딩
##실습
1. views.py 작성하기 전
django-admin startproject <project-name>
cd <project-name>
python manage.py startapp <app-name>
settings.py에 App, rest_framework추가
models.py에 모델 작성 및 migrate
serializer.py생성 및 작성
2. views.py 작성하기
1) 필요한 모듈 추가하기
- 사용할 모델, serializer , rest_framework 의 generics 추가
from .models import Post
from .serializer import PostSerializer
from rest_framework import generics
2) PostList 클래스 작성하기
- generics의 ListCreateAPIView 는 mixins에서 사용한 list 함수와 create 함수를 가지고 있는 class 이다.
class PostList(generics.ListCreateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
3) PostDetail 클래스 작성하기
- genercis의 RetrieveUpdateDestoryAPIView 또한 mixins에서 사용한 함수들과 동일한 기능
class PostDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
3. urls.py 작성하기
- 앱 내부에 urls.py 생성 및 작성
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views
urlpatterns = [
path("post", views.PostList.as_view()),
path("post/<int:pk>", views.PostDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
- 프로젝트 폴더 내부의 urls.py 에 include
from django.contrib import admin
from django.urls import path, include
import post.urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(post.urls)),
]
-> 실행 결과 : http://127.0.0.1:8000/post로 접속하면 잘 작동하는 것을 확인할 수 있다.
5. ViewSet
rest_framework의 viewsets.py내부에는 4개의 클래스가 존재한다.
ViewSet
GenericViewSet
ReadOnlyModelViewSet
ModelViewSet
모두 간단하게 구성되어 mixins와 GenricViewSet, APIView등을 묶는 역할을 한다.
ReadOnlyModelViewSet
- 상속 받은 클래스
mixins.RetrieveModelMixin
mixins.ListModelMixin
GenericViewSet
상속받은 클래스로 보아 해당 viewset 역할은 retrieve 함수와 list 함수 기능을 가지고 있다
- 기능 : 특정 객체 가져오는 역할(retrieve) / 객체 목록을 가져오는 역할(list)
ReadOnly를 수행하는 viewSet 이다
아래와 같이 작성하면
기존 postlist, postDetail 클래스의 기능을 따로 작성하지 않아도 ReadOnlyModelViewSet을 상속받아 사용할 수 있다.
from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer
class PostViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Post.objects.all()
serializer_class =
-> customAPI 함수는 default로 GET 메서드로 처리된다. / 다른 메서드로 처리하고 싶다면 action의 format 인자로 지정 가능
%action decorator
@는 decorator, 장식자라고 부른다. ViewSet을 이용하면 CRUD는 간단하게 구현되나 다른 논리들을 구현할 때 @action를 사용한다. 개발자가 임의로 View를 설계할 수 있도록 해준다.
%renderer_classes
Response를 어떤 형식으로 Rendering시킬 것인가를 정의
renderer.JSONRenderer
renderer.BrowsableAPIRenderer
renderer.StaticHTMLRenderer
TemplateHTMLRenderer
등 여러가지가 있다. 기본 설정은 JSONRenderer와 BrowsableAPIRenderer다.
##실습해보기
viewSet 적용하기
1. views.py 작성하기 전
django-admin startproject <project-name>
cd <project-name>
python manage.py startapp <app-name>
settings.py에 App, rest_framework추가
models.py에 모델 작성 및 migrate
serializer.py생성 및 작성
2. views.py 작성하기
1) 필요한 모듈 추가
from .models import Post
from .serializer import PostSerializer
from rest_framework import viewsets
from rest_framework import renderers
from rest_framework.decorators import action
from django.http import HttpResponse
2) ReadOnlyModelViewSet을 상속해 클래스 작성하기
- viewsets의 ReadOnlyModelViewSet을 상속받아 작성한다. ReadOnlyModelViewSet을 상속받았으므로 읽기만 가능하다.
class PostViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
3. urls.py 작성하기
- post 앱 내부의 urls.py
from rest_framework.routers import DefaultRouter
from django.urls import include, path
from .views import PostViewSet
router = DefaultRouter()
router.register('', PostViewSet)
urlpatterns = [
path('post', include(router.urls))
]
- 프로젝트 폴더의 urls.py
from django.contrib import admin
from django.urls import path, include
import post.urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(post.urls)),
]
>>실행결과
-http://127.0.0.1:8000/로 접속하면 아래와 같은 결과를 확인할 수 있다. DefaultRouter를 사용했기 때문에 PATH가 ""일때도 화면이 나온다.
-http://127.0.0.1:8000/post로 접속하면 사용가능한 HTTP Method가 ReadOnlyModelViewSet을 상속받았으므로 GET밖에 없다.
4. ModelViewSet 상속해 클래스 작성하기
viewsets의 ModelViewset 상속받은 PostViewSet 클래스 작성
사용할 모델과 serializer을 등록하는 것은 기존과 동일
추가적으로 @action 데코레이터를 이용해 custom api 작성
get 방식으로 @action Custom API Test를 띄우는 highlight 함수 작성
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
return HttpResponse("@action Custom API Test")
post로 처리하고 싶다면 @action(method=['post']) 와 같이 작성
>>실행결과
http://127.0.0.1:8000/post로 접속하면 사용가능한 HTTP Method가 GET외에도 POST가 추가된 것을 확인
Custom API 테스트
>http://127.0.0.1:8000/post/2/와 같이 Detail페이지로 접속하면 Extra Actions 스크롤 메뉴가 생긴 것을 확인할 수 있다.
스크롤 메뉴에서 highlight 버튼 클릭 시 아래와 같은 결과가 생성된다
6. Router
viewSet 복습
- ReadOnlyModelViewSet
retrieve()와 list()의 기능
- ModelViewSet
list(), create(), retrieve(), update() partial_update(), destroy()의 기능
path
viewSet을 하나의 path 함수로 처리할 수 있을까?
하나의 path로 ListView, DetailView 의 CRUD가 모두 처리 가능할까??
-> 앱 폴더 내부에 urls.py 생성(계층적 url 관리 위해 분할) ##아니 나는 urls.py를 완성하지 못하면 마이그레이트가 안된다.. 이거먼저!
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter() #ROUTER 객체 생성
router.register('post', views.PostViewSet) #ROUTER 객체의 REGISTER 함수(첫번째 인자 = URL, 함수)
urlpatterns = [
path('', include(router.urls))
]
#rest_framework는 ROUTER을 사용해 URL을 결정한다
#CRUD 기반으로 URL을 설정한다
-> 프로젝트 폴더 urls.py 에 모듈 추가
from django.contrib import admin
from django.urls import path, include
import post.urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(post.urls)),
]
앱 폴더의 models.py 에 모델 클래스 정의 (post/models.py)
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
# Create your models here.
앱 폴더 내부에 serializer.py 생성 및 작성 (어떤 클래스의 어떤 필드를 사용할 것인지)
from .models import Post
from rest_framework import serializers
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['title', 'body']
# 모든 필드를 사용할 경우 '__all__' 사용 가능
views.py 작성하기
-> rest_framework 의 viewsets 모듈과 작성한 모델과 serializer 추가
from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
Django Rest Framework는 Class base View 이기에
view로서 class를 작성한다
viewsets의 ModelViewSet을 상속받는다.
##ROUTER
▪ ViewSet에는 여러가지 메소드(함수)들이 있다
ex) retrieve() , destroy(), …
▪ 이 모든 것을 하나의 path()로 처리해 주는 것은 불가능하다.
▪ Path함수를 묶어준다 == path함수의 두번째 인자로 오는 함수를 묶는다
-> Path(요청을 처리할 url, 요청을 인자로 받아 처리할 함수, namespace)
#실행 결과(api 서버 보기)
1. api root : urls.py 에 작성된 DefaultRouter 에 의해 만들어진 기본적인 환경 / 처음 보여지는 화면은 GET 요청을 할 수 있는 URL이 보여진다.
2.POST API
-request : 127.0.0.1/8000/post
-response
post 후 post/1로 들어가면 allow 부분에 put이 들어간 것을 볼 수 있음
각 객체에 pk 값 부여하기
-> serializer.py 파일의 PostSerializer 을 수정한다
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'title', 'body']
새로 고침 후 보면 id 값을 직접 확인할 수 있는 것을 볼 수 있다.
id 값 : 각 인스턴스에 붙는 고유 번호
Read Only 설정하기
-> serializer.py 파일의 PostSerializer을 수정한다
-> read_only_fields 에 read_only 속성을 적용할 필드를 tuple에 추가한다
-> 수정 시 read_only 부분이 true로 바뀌는 것을 볼 수 있다.
-> write_only부분도 같은 방법으로 수정하면된다!
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = "__all__"
read_only_fields = ("title",)
▪ Get 인자가 있으면 쓰고 없으면 안쓴다. ▪ Put 인자가 있으면 쓰고 없으면 안쓴다.
2. CBV
-장고의 view
- 호출 가능한 객체(callable object) 로 정의
-> 함수 / 클래스
- 함수와 클래스의 차이 : 함수 (상속x) / 클래스 (상속o)
- 상속을 사용하는 이유는 ? 중복의 제거 / 코드의 재사용
따라서 CBV를 사용하는 이유는 상속을 사용해 코드를 더 간단하게 작성하기 위해 사용
-FBV(Function Based View) : 함수 기반 뷰
##실습하면서 익혀봅시다
순서 : 프로젝트 생성 -> 앱 생성 -> 템플릿 추가
가상환경 생성 및 활성화
$python -m venv myvenv
$ source myvenv/Scripts/activate
프로젝트 생성
$ django-admin startproject CBV
$ cd CBV
앱 생성
$python manage.py startapp classBaseCrud
settings.py 에 앱 추가
INSTALLED_APPS = [ 'classBaseCrud', ]
models.py 작성하기
- 클래스 생성
from django.db import models
# 클래스를 생성하여 제목, 생성일, 수정일, 본문 필드 작성
class ClassBlog(models.Model):
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
#auto_now_add 옵션 : model이 최초 저장시에만 현재 날짜 적용
updated_at = models.DateTimeField(auto_now=True)
#auto_now 옵션 : 데이터가 저장 될 때마다 현재 날짜로 갱신
body = models.TextField()
def __str__(self):
return self.title
-admin.py에 생성한 클래스 등록
from django.contrib import admin
from .models import ClassBlog
admin.site.register(ClassBlog)
-Generic Views : 웹 개발 시 자주 사용하는 기능을 장고에서 미리 제공 / 외부 모듈 적용이 필요하다
#사용할 모듈 추가 CRUD
from django.utils import timezone
from django.urls import reverse_lazy
from django.views.generic.list import ListView
#게시글 목록 보여줌
from django.views.generic.detail import DetailView
#게시글의 상세 내용을 보여줌
from django.views.generic.edit import CreateView, UpdateView, DeleteView
#게시글 생성, 수정, 삭제
from .models import ClassBlog
2)모듈을 상속해 클래스 작성(classBaseCrud/views.py)
-CREATE
#CREATE
class BlogCreate(CreateView):
model = ClassBlog
fields = ["title", "body"]
success_url = reverse_lazy('list')
#reverse_lazy
#- redirect 와 같은 기능으로 , generic view에서 주로 사용
#- reverse_lazy() 함수 사용 인자로 URL 이름을 넣어줌
#- 작업이 성공적으로 완료되었을 경우 해당 URL로 이동
-READ
#READ
class BlogView(ListView):
model = ClassBlog
template_name = 'classBaseCrud/list.html'
context_object_name = 'blog_list'
# List Views
#- Generi view 중 특정 모델의 리스트를 출력해주는 뷰
#- 모델에 대한 쿼리가 필요하고(queryset)
#- 어느 템플릿에 (template_name)
#- 어떤 파라미터명으로 전달할지 (context_object_name) 를 정의
#- 약속되어있는 html 이름을 사용하지 않고 작성하기 위함
#- 해당 html을 사용할 class에 template_name을 설정하면 된다
#context_object_name : 임의로 설정하여 기본적으로 설정되어있는 객체를 가져옴
class BlogRead(DetailView):
context_object_name = 'blog'
model = ClassBlog
#DetailView
#- 특정 모델의 특정 오브젝트에 대한 자세한 정보를 출력해주는 뷰
#- 어떤 모델의 어떤 오브젝으를 어떤 템플릿에 전달할지 정의
-UPDATE
#UPDATE
class BlogUpdate(UpdateView):
model = ClassBlog
fields = ["title", "body"]
success_url = reverse_lazy("list")
-DELETE
#DELETE
class BlogDelete(DeleteView):
model = ClassBlog
success_url = reverse_lazy("list")
앱 내부에 urls.py 생성 및 작성
- 작성할 클래스에 맞는 url path 작성
- (urls.py / classBaseCurd)
from django.urls import path
from .import views
#작성할 클래스에 맞는 url path 작성
urlpatterns = [
path("", views.BlogView.as_view(), name='list'),
#as_view : view를 하나 만들어서 이를 return
#함수가 하나 만들어지는 것과 같음
#클래스를 정의한 후 이에 해당하는 함수 만들어 사용하는 방식
path("create/", views.BlogCreate.as_view(), name="create"),
path("read/<int:pk>/", views.BlogRead.as_view(), name="read"),
path("update/<int:pk>/", views.BlogUpdate.as_view(), name="update"),
path("delete/<int:pk>/", views.BlogDelete.as_view(), name="delete"),
]
프로젝트 urls.py 에 앱 urls.py 추가
- (urls.py / CBV)
from django.contrib import admin
from django.urls import path, include
#django.urls 의 include 모듈 추가
#앱의 urls.py 파일을 프로젝트 urls.py에 추가
import classBaseCrud.urls
import classBaseCrud.views
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(classBaseCrud.urls)),
]
templates 생성하기
- 수행 결과를 보여주는 HTML 템플릿이 존재해야하고 ListView 는 블로그 리스트 HTML / CreateView, UpdateView 는 입력공간(form)을 갖는 HTML
DetailView는 상세 페이지 HTML / DeleteView 는 삭제 작업을 확인하는 HTML 필요
- Generic View 에서는 기본적으로 설정된 이름이 존재
- 다른 이름으로 HTML 을 작성하기 위해서는 추가 설정이 필요
View 이름
HTML 이름
ListView
(소문자 모델)_list.html
CreateView
(소문자 모델)_form.html
DetailView
(소문자 모델)_detail.html
UpdateView
(소문자 모델)_form.html
DeleteView
(소문자 모델)_confirm_delete.html
##template폴더 구성할 때 template 안에 HTML 파일을 작성하는 게 아니라 App 이름의 폴더를 작성하고 그 안에 작성
SQL과의 비교(SQL count(*) 에서 group by 는 mongodb 집계와 동일)
select
$project, $group 함수($sum, $min, $avg 등)
from
aggregate()
join
$unwind
where
$match
group by
$group
having
$match
aggregation 표현식 목록
> db.mycol.aggregate([ {$group : { _id : "$by_user“ , num_tutorial : {$sum : 1} }} ]) //출력될 문서의 형식 { _id : 값1, num_tutorial : 값2 } //$가 붙은 문자열 필드 값은 일반 문자열 값이 아닌 입력 문서의 특정 필드를 지정
> db.mycol.aggregate([{$group :{_id :"$by_user", num_tutorial :{$sum :1}}}]) { "result":[ { "_id":"tutorials point", "num_tutorial":2 }, {"_id":"Neo4j", "num_tutorial":1 } ],"ok":1 }//각 사용자가 작성한 자습서 수 나타내는 목록
$sum -> 각 그룹에 대해 그 그룹에 속하는 문서가 있을 때 마다 num_tutorial 필드 값을 1씩 증가
$avg -> 컬렉션의 모든 문서에서 제공된 모든 값의 평균 계산
$min -> 컬렉션의 모든 문서에서 해당 값의 최소값 가져옴
$max -> 컬렉션의 모든 문서에서 해당 값의 최대값 가져옴
$push -> 결과 문서의 배열에 값 삽입
$addToSet -> 결과 문서의 배열에 값을 삽입하지만 중복은 생성하지 않는다
$first -> 그룹화에 따라 소스 문서에서 첫 번째 문서를 가져옴 / 이전에 적용된 일부 "$sort" 단계와 만 의미 O
$last -> 그룹화에 따라 소스 문서에서 마지막 문서를 가져옴 / 이전에 적용된 일부 "$sort" 단계와 만 의미 O
// 배열 points의 요소들 중에 (15보다 큰 조건만을 만족하는 요소도 있으면서 20보다 작은 조건을 만족하는 또 다른 요소도 있는 문서) 또는 (한 요소가 15보다 크면서 20보다 작은 조건을 모두 만족)하는 문서 검색 > db.myCol.find( {“points”:{$gt:15, $lt:20} })
// 배열 points의 요소들 중에 적어도 하나라도 (21보다 크고 26보다 작은 조건을 모두 만족)하는 요소를 가지는 문서 검색 > db.myCol.find( {“points”:{$elemMatch:{$gt:21, $lt:26}} })
Q1) 이름이 joo이고 나이가 24인 친구를 가지고 있는 사람의 이름은? Q2) 나이가 22살 이하인 친구를 가지고 있는 사람의 이름은? Q3) 첫 번째 친구의 나이가 20인 친구를 가지고 있는 사람의 이름은?
2. Indexing(인덱스)
몽고 디비 쿼리에서 효율적인 실행을 지원 -> 인덱싱이 없이 몽고디비는 콜렉션 스캔을 실행하여야 한다. -> ex) 쿼리문에 일치하는 도큐먼트 선별하기 위해 컬렉션 내의 모든 도큐먼트를 스캔해야한다
인덱스 : 콜렉션의 데이터셋의 작은 일부를 저장하고 있는 특별한 데이터 구조 -> 인덱스는 특정 필드 또는 필드 세트의 값을 인덱스에 지정된 필드 값 순서로 저장 -> 컬렉션내의 임의의 문서를 빠르게 접근하도록 하는 자료구조 ->인덱스는 데이터 파일과는 별도의 파일에 저장됨 ->검색 속도를 향상시키나 인덱스 저장 공갂 필요 -> 삽입, 삭제, 수정 연산의 속도 저하
인덱스의 구조 -> 엔트리 구조 : < 탐색 키 필드, 문서에 대핚 포인터 > ->엔트리들은 탐색 키 필드 값의 오름차순으로 정렬되어 있음
다단계 인덱스 : B, B+ 트리 사용
1) ensureIndex() 메서드
db.COLLECTION_NAME.ensureIndex({KEY : 1})
-> key 는 색인을 작성하려는 필드의 이름 / 1은 오름차순 / 내림차순으로 인덱스를 만들려면 -1
-> 여러 필드에 인덱스를 만들려면 여러 필드를 전달할 수 있다.
>db.mycol.ensureIndex({"title" : 1}) >db.mycol.ensureIndex({"title":1,"description":-1}) //여러 필드 전달
ensureIndex() 메소드는 옵션 목록도 허용합니다.
PARAMETER
TYPE
DESCRIPTION
background
boolean
인덱스를 빌드해도 다른 DB 활동을 차단하지 않도록 백그라운드에서 인덱스를 빌드한다. 백그라운드에서 빌드하려면 TRUE / 기본값은 FALSE
unique
boolean
인덱스 키가 인덱스의 기존 값과 일치하는 문서 삽입을 허용하지 않도록 고유 인덱스를 생성/ 고유 인덱스를 작성하려면 TRUE 지정 / 기본값은 FALSE
name
string
인덱스의 이름/ 지정되지 않은 경우 mongodb는 인덱스화 된 필드의 이름과 정렬 순서를 연결하여 인덱스 이름을 생성
dropDups
boolean
중복될 수 있는 필드에 고유 인덱스를 작성 / mongodb는 키의 첫번째 항목만 인덱스화하고 해당 키의 후속 항목이 포함된 콜렉션에서 모든 문서를 제거 / 고유 인덱스를 작성하려면 true를 지정/ 기본값은 false
sparse
boolean
true인 경우 인덱스는 지정된 필드가 있는 문서만 참조 / 이 인덱스는 공간을 덜 사용하지만 일부 상황(정렬..) 에서 다르게 동작 / 기본값 false
expireAfterSeconds
Integer
mongodb가 콜렉션에서 문서를 보유하는 기간을 제어하기 위해 TTL 값을 초 단위로 지정
v
Index Version
색인 버전 번호 / 기본 인덱스 버전은 인덱스 작성시 실행중인 mongodb 버전에 따라 다름
weights
Document
가중치는 1~99,999 범위의 숫자, 점수를 기준으로 다른 색인화 된 필드에 대한 필드의 중요성 나타냄
default_language
string
텍스트 인덱스의 경우 중지 단어 목록과 형태소 분석기 및 토크 나이저에 대한 규칙을 결정하는 언어 / 기본값 english
language_override
string
텍스트 인덱스의 경우 기본 언어를 대체 할 언어를 포함하는 문서의 필드 이름 지정 / 기본값은 언어
2. 커서(5주차 추가 메뉴얼)
커서의 활용
find() 메소드 : 검색된 문서 집합에 대한 커서 반환
var 타입의 번수 사용하지 않는 경우
// mongo 쉘에서는 반환 결과를 변수에 할당하지 않으면 // 커서가 자동으로 20번 반복되어 문서 20개를 자동 출력 후 대기 // “it” 입력하면 커서 반복 > db.myCol.find()
var 타입의 변수 사용하는 경우
반환된 문서 집합에 대해 커서를 수동으로 반복하여 개별적 문서 접근
> var myCursor = db.myCol.find() > myCursor // 커서 20번 반복 -> 20개 문서 출력 후 대기
> var myCursor = db.myCol.find() > while (myCursor.hasNext()) { print(tojson(myCursor.next())); // printjson(myCursor.next()); }
커서 활용
검색 결과의 문서 개수 출력
> db.myCol.find.count() > var res = db.myCol.find.count() > res
3. Index 메소드
인덱스 생성 메소드 //createIndex()
db.컬렉션명.createIndex(<키> , <옵션>) // <키>는 문서 형식 {키:1 or -1, ... }으로 명세 (1:오름, -1:내림) // <옵션>도 문서 형식 {키:값, ... }으로 명세
단일 / 복합 인덱스 (single / compound index) 생성
db.mycol.createIndex({"age" : 1}) //단일 키 인덱스(하나의 필드만 사용)
db.mycol.createIndex({"deptname" : 1, "year" : -1}) //복합 키 인덱스 (2개 이상의 필드 사용) //키의 순서 중요