태그 글목록: mongodb

Icon_MongoDB_by_xkneo

mongodb batch (1)

몽고디비에서 돌아가는 배치 프로그램을 작성 할경우  콘솔에서 아래처럼 실행 할수 있다.
(로컬에서 실행중이고 디폴트 포트일경우)

$ mongo < batch.js

이때 저 batch.js 안에 외부 자바스크립트 라이브러리를 load 해서 작성 할수 있다. json 데이터를 다루는 만큼 underscore.js 같은걸 쓰면 데이터 조작이 아주 편할꺼 같다고 생각, 테스트 한 결과는 아래와 같다. 순서는

1. 외부소스를 로딩하고
2. 원하는 디비로 이동해서
3. 질의를 시작하여 결과를 array 로 변환한뒤
4. array 의 모든 요소를 다른 쪽디비(mola)로 등록한다.

기타 print(몽고쉘명령) 명령 으로 실행 결과를 출력하여 확인 할수 있다.

 

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious
Icon_MongoDB_by_xkneo

왜 몽고디비에서는 object 검색이 잘 되지 않는가?

왜 몽고디비에서는 object 검색이 잘 되지 않는가?

*db.orders.find(   { info : { name : ‘박승현’ , age : 20 } }   );  이런 질의가 있다고 가정해보자.  이걸 몽고 디비에서는 **db.orders.find(   {$and : [ {‘info.name’ : ‘박승현’} , {‘info.age’ : 20} ]}  ) 으로 해야 정확한 결과가 나온다. 만약 orders 컬렉션에 해당 문서가 { info : { age : 20 , name : ‘박승현’ } , year:2014 }  라고 들어 있으면 첫번째질의는 검색이 되지 않는다. (하위 오브젝트의 순서가 바뀐것)

즉, 몽고디비는 name 이 ‘박승현’이고 age 가 20 인 doc 를 검색 하지 않는다. 그저 info 라는 key 에 value 값을 무슨 String 값이나 binary 처럼 단순 비교함을 유추할수 있다.

왜 일까? 만약 doc 가 단순한 수준이 아니라 1.하위에 여러 depth 를 가지고 있다거나 2.배열이라거나 3. key 가 8760개가 들어있는 시계열 데이터 문서들을 저장한 컬렉션 이라면? 이런 모든 경우의 수를 json 으로 인식해서 검색해주면 정말 눈물나게 고맙긴 하겠지만 아마 그 속도때문에 느려터진 괴물로 생각하고 버렸을것이다.

그럼 어떻게? “Dot notation” 또는 “$and, $or, $in …. ” 등의 선언자들을 써줘야 우리 몽고디비 파서는 질의를 판단해서 오브젝트 하위나 배열을 뒤저야 겠구나 생각하고 그제서야 bson 을 파싱해서 하위 오브젝트 까지 관심을 갖는것. 결국 몽고디비는 별다른 조건이 없으면 첫번째 level 의 key 가 가진 value 값만 “단순 비교” 한다는 것. 

이건 몽고디비의 사상이다. 속도를 위해서 디테일한 편의를 포기하는것.(실제로는 다른형태로 제공) “object 단위로 검색이 되지 않는다” , “쿼리가 너무 불편하다” 등 속도를 포기해야 하는 이런 기능에 대하여 불편을 느낀다면 몽고디비같은건 만들어 쓰자. 우린 개발자니까.

 

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious
angularjs-188x200

angularjs 와 java , mongodb 사용의 나쁜예 퀵하게 보기 (1)

현재 angularjs 와 java(톰켓)을 사용하여 SI 프로젝트를 하고 있습니다. 현시점에서 상태를 퀵하게 기술해봅니다.  전체를 상세 설명하려면 소스 공개가 가장 빠르겠지만 SI 특성상 공개 할수가 없습니다. 제 개발 패턴이 궁금하신분이 있다면(없겠지만) 차라리 데모?를 직접 보여 드릴 수는 있습니다. ㅎㅎㅎ

front : javascript ( angularjs 를 주로 씀 )
was : java / tomcat / struts2 / spring(젤 하는일없음)
db : mongodb 
o/s : dev-osx , server-ubuntu

1. 클라이언트

1.1 코딩기준 
	- jQuery 떡칠 way 는 하지 않고 (아예사용안함) angular way 로만 한다. 
	- single web page 로 구성한다. 
	- index.html 상단과 좌측 메뉴 처리 , appControl 관련된 javascript 처리
		-> 실제로 메인 app. 메인 컨텐츠 부분은 ng-view 로 동적 로딩 되게 한다. 
	- 동적 로딩되는 실제 ui 처리는 ng-view와 router 를 사용한다. 
          로딩되는 화일은 화면명.html + 화면명Ctrl.js 의 한쌍으로 구성한다.
		-> 개인적인 취향 jQuery 떡칠패턴으로 개발시부터 
                   ui.html + ui.js + ui.css를 주로 써왔음
	- 디렉티브는 별도로 저장한다. 
	- 전체 화면의 공유 데이터는 rootScope 데이터 변수를 사용하여 공유한다.
		-> service 는 사용하지 않는다 (angularjs 권고사항) 

1.2 폴더
	/estimate 	- index.html 및 화면명.html , 화면명Ctrl.js 화일들 저장 
	|- /directive	- angularjs 디렉티브 + ui.bootstrap 디렉티브
	|- /filter	- 필터관련 js 화일
	|- /helper	- 메뉴처리 js , 기타 분류안한 js 예) request 처리 js
	|- /service	- view Controller 에서 공통 사용되는 업무관련 함수들
			  ex) 몽고디비기본함수 (find,remove,update..) 클라이언트 구현체 
	/lib		- 외부 자바스크립트 프레임워크들 
	|- /bootstrap
	|- /Hightchart 
	|- underscore.js

	/schema
		schema.js   - json템플릿 리턴 및 벨리데이션 담당
		schema.json - json 스키마정의 

2. 서버 (tomcat)
	2.1 어떠한 경우도 서버페이지(jsp) 를 생성하지 않는다. 
	2.2 브라우저 요청과 서버쪽 Action 은 이름으로 매칭한다. (설정최소화)
	    -예) 클라이언트 요청 SalesEstimate-findProject 
		 -> 서버쪽 처리    SalesEstimateAction 의 findProject
	2.3 브라우저 리프레쉬 할경우 클라이언트 라우터 동작을 위한 리디렉트 구현
	2.4 odm 은 하지 않는다. jsonhashmap 변환으로 대체 (gson 라이브러리사용)		
		key 값을 method 로 사용하지 않음. key 값을 검색의 대상으로 동적 사용하므로 불가능함. 
	2.5 향후 node 로 변환 or 스프링및 스트러츠 걷어내고 jsp 만으로 전환.

3. issue 
	router시 앵귤러 해쉬뱅 '/#/' 으로 인해서 ie 에서 비정상적 동작. 
           1. 심각하게 "angularjs 들어 내기" , "single web 안하기" 중에 고민중.
           2. 앵귤러들어내기 (meteor 에서 ddp만 내리고 클라이언트만 사용하기)
        "서버가 자바인 관계로 자료구조(json) 핸들링의 어려운점" 해결방안 모색
           1. 자바들어내기 - 현재는 hashmap 으로 꿋꿋하게 버티는중.

소스나 개발 패턴이 좀더 나아지면 (2)탄도 써보겠습니다.

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious
Icon_MongoDB_by_xkneo

몽고디비 “stored function” 퀵하게 보기

스토어드 프로시져를 보기!  json의 특성을 조금 알면 아주 잘됨.

/*저장*/
db.system.js.save({_id:"addNumbers", value:function(x, y){ return x + y; }});

/*호출*/
1. 안추천 하고 싶은 방법
db.eval('addNumbers(17, 25)')

2. 추천 하는 방법
db.system.js.find({_id:"addNumbers"}).value(3,4)
이렇게 호출하면 쵝오 잘됨

역시 mongodb 는 json 을 착실히 저장함.
그렇다면 당연히 함수도? Yes!

그럼 테스트~! (a,b 바꿔가면서 insert 서너번 해주면 눈에 잘띔)

db.test.insert({
a : 1
,b : 2
,addAll : function(){ return (this.a + this.b); }
,queryTest : function() { return db.test.find(); }
});

1. db.test.findOne().addAll()    /*현재 doc의 속성들을 접근 해서 결과를 리턴*/
2. db.test.findOne().queryTest() /*프로시저를 doc에 내맘대로 저장됨*/

자세히 들여다 보면 addAll 이란 code type 의 속성을 가진 필드가 저장이됨.

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious

신조어 생성 – 계정 샤딩

신조어 – 계정 샤딩 

미션 – UI 의 모든 이벤트를 로그로 쌓는다. 공짜로.

방법 : 계정샤딩(ID Sharding) 

준비물  : 구글 계정 10개, 노드 서비스 하나 호스팅 (appfog정도면 훌륭)

1. 준비한 구글계정 10개로 mongohq 계정 10개 판다.

2. 로그를 저장할 프로그램에서 id 를 atoz로 10개 계정으로 나눠서 저장하는 코드를 짠다.
-> 어짜피 json 은 join 이런거 후져서 다때려박으니(embedded pattern) 문제없음.

3. 생성할때는 10개의 서버가 있는셈 : 겁나 빠르겠지?
조회할때는 10개큐에 계정정보를 동시에 날려서 promise (jQuery promise같은거 구현해야겠다) 받은뒤, 리턴받은 10개를 reduce 구현 하면 됨. 하둡이 따로없어!!

p.s : 몽고 샤딩:계정샤딩 = 파티션테이블:프로그램코딩

이랄까?

와 진짜 좋은생각~!!! 잠이 확깬다~!! 계정 샤딩 만쉐~!!

일단 ID 샤딩 구현하고 , 그담번에는 계정 레플리카도 생각해봐야지… 씐난다~!

 

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious

mongodb sparce index 퀵하게 보기

* mongodb의 index 특징 몇가지
-. array에 index 가능, 각각의 원소가 _id 와 함께 indexing 이됨
-. multi key index가능 : 단!!! 2개 key 이상 모두 배열로 insert 안됨!!
-. unique index 는 key가 없이 insert 될경우 key:null 로 간주하여 dupkey 에러 발생!!

* sparce index 
-> unique index 생성시 key 값이 없어도 insert 가 가능하게함

key로써 a,b,c 가 존재 하는 document 에서
unique와 함께 c로 index 를 걸었을경우
db.test.ensureIndex({c:1},{unique:true, sparse:true}) /* ensureIndex 함수이용 */

a:1 , b:2 , c:3  -> indexing 대상
a:1 , b:3           -> 제외
a:2 , b:3           -> 제외

스파스 인덱스는 인덱스 선언된 key 가 없는 doc의 경우 인덱싱에서 제외됨
-> 인덱스를 통해 접근할경우 key 가 없으면 쿼리 대상에서 제외된다는 이야기
-> 인덱스를 건 시점에서 쿼리 결과가 달라질수 있음
ex) sort 를 할경우 대상에서 제외되버림
-> 초반설계시에 key (컬럼)이 없이 insert 된넘들 ($exists 구문없이) 무시하기에 딱좋겠다.
<퀵하게 보기 끝>

테스트 해보자

테스트 데이터 넣고

> var t = db.test
> db.t.insert({a:1,b:2,c:3})
> db.t.insert({a:4,b:6})
> db.t.insert({a:9,b:11})
> t.find()
{ "_id" : ObjectId("514d541dc19f83d03d5b7706"), "a" : 1, "b" : 2, "c" : 3 }
{ "_id" : ObjectId("514d543cc19f83d03d5b7707"), "a" : 4, "b" : 6 }
{ "_id" : ObjectId("514d5441c19f83d03d5b7708"), "a" : 9, "b" : 11 }

이빨빠진 “c” key 로 index 걸어보기

> t.ensureIndex({c:1},{unique:true})
E11000 duplicate key error index: ppillip.test.$c_1  dup key: { : null }

-> 역시에러

그럼 이제 unique + sparse index 시도

> db.test.ensureIndex({c:1},{unique:true, sparse:true})

find 로 전체검색 해보면

> t.find()
{ "_id" : ObjectId("514d541dc19f83d03d5b7706"), "a" : 1, "b" : 2, "c" : 3 }
{ "_id" : ObjectId("514d543cc19f83d03d5b7707"), "a" : 4, "b" : 6 }
{ "_id" : ObjectId("514d5441c19f83d03d5b7708"), "a" : 9, "b" : 11 }

잘나오네

그럼 index 타게 sort 해보면

> t.find().sort({c:1})
{ "_id" : ObjectId("514d541dc19f83d03d5b7706"), "a" : 1, "b" : 2, "c" : 3 }

역시 “c” 없는 document는 무시당했어!! $exists 구문은 안써도 되겠다!

내생각
RDB : (db설계/수정 <-> 개발/수정) * n
noSql : (개발/수정 -> db 반영) * n
“간단하고 빠르게 개발자 위주로 가기는 nosql이 유리하다”는 내생각을 다시한번 확인함

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious

몽고디비 2.4 릴리즈 퀵하게 보기

거칠게 요약. 사실 좀 자세히 조목조목 테스트를 더 해봐야 겠슴.

Hash-based Sharding
-> 샤딩키를 해쉬로 해서 특정 범주에 몰리는것을 방지 함. 근데 다른 제약이 잇음. 걍 DBA 입장에서 slice 안해도 된다는거 빼고는 글쎄..

Capped Arrays
-> 다큐먼트내에 고정길이 배열을 사용할수 있게함. $push 하면 뒤에 것이 trim 됨. 사실 여기저기 $push 와 $pop 을 동시에 할수 있게 해달라는 요청이 많은걸 봤는데 바로 구현했네 ㅋ

Text Search (Beta)
-> 텍스트 서치! 개인적으로 제일 관심이 감!
사용법도 그다지 어렵지는 않아!.. score 도 있넹
블로깅으로 자세히 설명 http://goo.gl/axHtF

Geospatial Enhancements
-> 2차원 쿼리를 좀더 강화. 지도상에서 다각형의 교차 집합에 대한 쿼리를 추가 했다고함.

Faster Counts
-> 카운트시 전체 document 에 접근하지 않고 셀수 있다네요. 얼마나 빨라졌는지 해봐야겠다.

Working Set Analyzer
-> “making it easy to measure the percentage of resources used”
이게 핵심.

V8 JavaScript engine
-> MapReduce 속도 향상을 위해서 V8엔진으로 교체 했다는데 나잇스!
그래도 10gen 에서 말하길 2.2 이상에서는 aggregation 을 C로 구현해놔서 js 의 mapreduce 보다 빠르다고함.

Security
-> 커베로스 인증하고 역할 기반 접근제어(Role Based Access Control) 를 추가 했다는데 역할기반은 ACL 같은건가.. 이건좀 파봐야겠다.

사실 살짝 기대했던건 10gen 에서 I/O 시에 블락 패턴으로 구현됬다고 해서 확 깼었는데. 이부분에 아직 해결 안된듯. 음.. 아쉽다.

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious

mongodb 검색조건 트릭

json의 같은 level 내의 key 값 중복에 대한 성질과도 관계있는 검색조건 트릭에 대하여 정리해봅니다.

select * from users where age > 10
표현을 몽고 nosql 문장으로 표현한다면?
db.users.find({age:{$gt>10}});

select * from users where age > 10 and age < 20 표현을 몽고 nosql 문장으로 표현한다면? (복수 선택 가능) 1. db.users.find({ age : {$gt:10,$lt:20} }) 2. db.users.find({ $and : [ {age:{$gt:10}} , {age:{$lt:20}} ] }) 3. db.users.find({ age : { $gt : 10 }, age : { $lt : 20 } }) (아... 열라 복잡해.. 괄호지옥이다;;) 첫번째는 정답입니다. 그리고 제일 간단하고 직관적으로 보입니다. 괄호지옥이지만 그중에서 제일 심플하지요. 몽고디비에서 속도가 빠른 패턴이랍니다. 두번째는 정답입니다. 같은 패턴으로 $or 가 있습니다. 몽고 nosql 사용시 정석?문법입니다. 세번째는 오답입니다. 결과가 age < 20 인 모든 document를 리턴합니다.
좀더정확히 말하자면 “age가 20보다 작은, 모든 document를 포함한 커서” 를 리턴합니다.
json 이 같은 레벨에서 키값 중복을 허용하지 않습니다. 불행히도 중복 정의 한다고 해도 에러를 리턴 하지도 않습니다. 그래서 뒤에 값만 반영됩니다. 쉽게 확인해보시려면 브라우저나 node 아님 그냥 몽고 shell 에서 다음과 같이 해보세요

> var a = {age:10,age:20};
> a
{age:20}

이렇게 됩니다.

그래서 키값 한개에 범주 같은 중복조건을 주려면 1.번 패턴이 가장 빠르다고 합니다. 2.번 패턴은 가장 정석 패턴입니다.

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious

mongodb aggregation (distinct)

mongodb 의 distinct 는 어떻게 할까

step 1. 테스트 데이터 만들어 넣기
* 몽고디비 접속 옵션중 –shell 옵션을 사용하여 js 화일을 로딩합니다. js 화일에 선언되어있는 함수나 셋팅을 현재 세션에서 사용 할 수 있습니다.

step 2. map reduce 를 이용해서 값을 가져오기

step 3. aggregation 함수를 사용해서 시도
* aggregate 함수는 mongodb ver 2.2.0 이상에서 지원 됩니다.
* 함수 사용법은 aggregate([{필터},{필터},{필터}]) 와 같습니다. 자세한 내용은 “http://docs.mongodb.org/manual/aggregation/” 에 가시면 볼수 있습니다.

결과값

{
    "result" : [
    {
        "_id" : { "a" : "여수", "b" : "파주"},
        "n" : 2
    },
    {
        "_id" : { "a" : "서울", "b" : "일본"},
        "n" : 1
    },
    {
        "_id" : { "a" : "강릉", "b" : "서울"},
        "n" : 1
    },
    {
        "_id" : { "a" : "서울", "b" : "시드니"},
        "n" : 2
    },
    {
        "_id" : { "a" : "파주", "b" : "서울"},
        "n" : 1
    },
    {
        "_id" : { "a" : "서울", "b" : "서울"},
        "n" : 5
    }
],
    "ok" : 1
}

*몽고디비의 aggregate 는 bson 을 C 로 만들어서 조금더 속도가 낫다는 10gen의 언급이 있습니다.

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious

mongodb Sharding 요약 정리

몽고디비의 샤딩 실습 결과
->  replication 은 제외하고 구성 (추후에 언급)

 

1. 샤드 서버 2개 띄워 본다.

./mongod –shardsvr –port 27018 –dbpath /data/db
./mongod –shardsvr –port 27001 –dbpath /data/db27001

 

2. 콘피그 서버 1개만 띄워본다

./mongod –configsvr –port 27019

 

3. 서비스를 mongos로 띄워본다

./mongos –configdb ppillip.local:27019
—> 콘피그 서버 포트를 물고 띄웁니다. client (어플리케이션서버) 가 접속해야할 서비스 입니다.

 

4. 서비스에 접속합니다.

./mongo –shell week6.js localhost/week6
첫번째 arg : 몽고디비 콘솔 자체가 자바스크립트라서 –shell 옵션으로 사전 정의 해놓은 유틸이나 함수가 들어있는 js 화일을 같이 로딩하여 편하게 씁니다.
두번째 arg : 접속할 호스트와 db 명을 “/”로 구분하여 넣어줍니다.

4.1 샤드를 추가 해야지요

mongos> sh.addShard(“shard0000/ppillip.local:27018”)
mongos> sh.addShard(“shard0001/ppillip.local:27001”)
-> 첫번째 addShard 하고나서 데이터가 너무 많기 때문에 두번째 샤딩을 하는것이겟지요. 세번째도 네번째도 마찬가지구요. 이럴때마다 balancer 란놈이 개입을해서
데이터를 샤드별로 공평히?나누어 줍니다.

 

4.2 샤드를 enable 합니다.

mongos> sh.enableSharding(“week6”)
week6는 디비명 입니다.

 

4.3 자.. 이제 컬렉션을 갈라 볼까요

샤딩해줄 컬렉션에 인덱스를 걸어 봅니다. 원래 이런건 운영중일때 당연이 걸려있었겠지요.
mongos> db.trades.ensureIndex( { ticker:1, time:1 } )

 

4.4 이제는 컬렉션을 샤딩에 추가 해볼께요. (컬렉션명,키,유니크여부)

mongos> sh.shardCollection(“week6.trades”,{ticker:1 , time:1})

만약 운영중에 샤딩프로세스(mongod)를 추가 하고 싶으면 1)번 4.1)번을 해주면 됩니다.
물론 접속은 mongos 에 접속 하겠지요.

설명이 너무 rough 해서 죄송 합니다.

  • Facebook
  • Google Plus
  • Twitter
  • LinkedIn
  • Pinterest
  • Tumblr
  • Instapaper
  • Delicious