본문 바로가기
코드이그나이터와 php7와 mysql

PHP, 몽고 DB 에서 Command 로 갯수 세기

몽고DB에도 count(*)이 있나요?

itadventure.tistory.com/376

 

AWS(아마존 웹서비스) 몽고DB + php 드라이버 설치

몽고DB를 보면 볼수록 그 매력이 더한것 같습니다. 비록 관계형 데이터 베이스처럼 간단하게 한줄로 group by 문을 통한 통계를 낼 수는 없지만, 맵 리듀스라는 기술을 이용해서 가능하고, 맵 리듀

itadventure.tistory.com

지난 시간에는 몽고 db에서 자료를 삽입하는 부분을 다뤄보았습니다.
사실 지난 시간에 다룬 것은 몽고db의 라이브러리인 composer 측 확장 소스를 다룬 것이었는데요.
몽고 DB는 이렇게 확장소스로 제어할 수도 있지만,
지난번 pecl 로 컴파일하였던 몽고 db 본래 mongo.so 모듈에 있는 기본 PHP 함수로도 제어가 가능합니다.

이번 시간에는 이 부분을 다루어 보겠습니다.


mongo.so 모듈이 작동되고 나면 PHP에서는 몽고DB 내장 클래스인 아래 클래스를 사용할 수 있습니다.

MongoDB\Driver\Manager()

처음에는 도대체 이 소스가 어디 들어 있나 아무리 찾아봐도 안보이더라구요.
결국은 검색신공을 발휘한 결과 이 클래스는 몽고DB 의 진입 클래스인 것으로 확인되었습니다.
그러니까 php 소스가 아닌 c 소스에서 제공해주는 클래스라는 것이라는 것이지요.

그냥 네임스페이스까지 포함해서 PHP 의 일부가 되어 버린 것입니다.
결국 이런 모양의 네임스페이스 클래스를 통해 몽고 DB 로의 진입이 시작됩니다.

아래와 같은 소스를 보신 적이 있다면 이 함수는 PHP7 이 되기 이전에 사용되던 몽고 DB 클래스인 것으로 확인됩니다.
주로 PHP5에서 사용될 겁니다.

$manager = new Mongo();


아쉽지만 PHP7에서는 이 방식이 지원이 안되더군요.
몽고DB 관련 서적을 하나 샀는데 바로 이 방식이라 이론적인 부분을 제외하고는 별 쓸모없게 된 것 같습니다.
하지만 중고책으로 싸게 샀기에 다행입니다 :)

PHP7에서 가장 간단한 몽고DB 연결방법은 아래와 같습니다.

$manager = new MongoDB\Driver\Manager();

그리고 나서 지난번의 입력했던 책의 갯수를 세어보는 통계 함수를 사용해 봅시다.
PHP로 반복 함수를 돌리는 것보다는 몽고DB 본연의 기능을 사용하는 것이 속도면에서 빠르게 메모리면에서도 더 절약이 될 겁니다 :)

몽고DB의 통계 기능은 mysql보다는 좀 복잡합니다.

우선 아래와 같은 갯수를 추출할 몽고커맨드를 만들어줍니다.

$command = new MongoDB\Driver\Command([
    'count' => 'book',
    'query' => ['author' => 'cray'],
    'maxTimeMS' => 1000,
]);

갯수 추출시 3개의 파라미터를 주어주는데,
첫번째 파라미터 'count'에는 갯수를 산출할 컬렉션을 적어줍니다.

그리고 두번째 파라미터 'query'는 검색조건을 정해주는 것인데요.
배열을 통해 여러개의 조건을 콤마로 정해줄 수 있습니다.
['author' => 'cray'] 는 저자항목(author)이 'cray'와 일치하는 책만 고르는 것이지요.
그리고 세번쨰 파라미터 'maxTimerMS' 는 제한 실행시간입니다. 1,000값이 주어졌는데 그 의미는 1초(1000밀리초)라는 뜻이지요.

mysql의 경우 아래 2줄의 쿼리면 해결되었지만 몽고DB 는 좀 복잡해진 듯 합니다.

$qry=mysqli_query("select count(*) from book where author='cray'");
$row=mysqli_fetch_assoc($qry);

참고로 조건없이 컬렉션의 모든 도큐먼트 수를 구할 경우 아래와 같이 사용하면 됩니다.

$command = new MongoDB\Driver\Command(['count' => 'book']);

이렇게 갯수를 추출할 커맨드를 정해준 다음에는
실행을 하고 커서를 가져옵니다.

$cursor = $manager->executeCommand('craydb', $command);

커서란, 현재 위치를 의미합니다.
보통 MYSQL이나 MSSQL의 프로시저에서 사용하는 개념인데요.

우선 이런게 있다고만 알아 둡니다. 커서는 위치만 가리킬 뿐 데이터가 들어있지 않습니다.
var_dump 를 찍어봐도 아무런 결과가 나오지 않는데, mysql 과 비교하자면 mysqli_query()까지만 실행한 것과 유사합니다.

이제 실제 갯수를 받아오는 명령은 아래와 같습니다.

$total = $cursor->toArray()[0]->n;

 

 

식이 좀 복잡해 보이는데요.
먼저 $cursor->toArray()커서의 모든데이터를 배열로 받아옵니다.
자료가 10개면 10개를 받아오겠지만 이 경우 검색결과의 갯수라는 정보는 단 하나이기 때문에
배열의 갯수는 단 하나만 받아옵니다.
[0] 은 그 중 첫번째 배열을 의미하고,
그 배열안에는 n과 ok 라는 속성정보가 결과값으로반환됩니다.
n이라는 속성정보갯수를 의미하고, ok라는 속성정보는 성공한 경우 1이지만 별 의미는 없습니다
->n 표현식은 n 이라는 속성정보를 의미합니다.
결국 갯수를 받아오는 것이지요.

마지막으로 이 결과를 출력하면 되는 것입니다.

echo $total."건";

크레이의 경우 지난번 소스를 6번 가량 돌린 탓에, 아래와 같이 결과가 나왔습니다.

12건

이상으로 몽고DB컬렉션의 조건에 따른 갯수를 추출하는 부분을 다뤄보았습니다.
전체 소스는 아래와 같습니다.

<?
$manager = new MongoDB\Driver\Manager();

// 통계 산출 ( count )
$command = new MongoDB\Driver\Command([
    // book 컬렉션에서
    'count' => 'book',					
    // 검색조건 : 저자가 cray인 것만
    'query' => ['author' => 'cray'],	
    // 제한 시간 1초
    'maxTimeMS' => 1000,		
]);

// 커맨드를 실행하고 커서를 가져옴
$cursor = $manager->executeCommand('craydb', $command);
// 커서로부터 통계 추출
$total = $cursor->toArray()[0]->n;

echo $total."건";

만일 이를 간단히 사용하고 싶다면 아래와 같이 기능을 모듈화할 수 있습니다.
크레이가 만든거니 자유롭게 사용하세요.
그리고 crayMongo.php 로 저장하겠습니다.

<?
// 통계 산출 ( count )
// 입력)
//   $dbname :  DB명
//   $collection : 컬렉션명 
//   $query : 검색조건 ( ['author' => 'cray'] )
//   $maxTimeMS : 제한시간ms(밀리세컨드), 기본 1,000
function crayMongoCount(&$manager, $dbname, $collection, $query, $maxTimeMS=1000)
{
	// 통계 산출 ( count )
	$command = new MongoDB\Driver\Command([
			'count' => $collection,								// book 컬렉션에서
			'query' => $query,	// 검색조건
			'maxTimeMS' => $maxTimeMS,							// 제한시간 1초 안에 산출
	]);
	// 커맨드를 실행하고 커서를 가져옴
	$cursor = $manager->executeCommand($dbname, $command);
	// 커서로부터 통계 추출
	return $cursor->toArray()[0]->n;
}
?>

이 소스를 include 시키고 활용하는 방법은 아래와 같습니다.
매우 간단해 졌지요? 이전과 실행 결과는 동일합니다.
만일 여러 컬렉션에 이런 count 기능을 적용하려면 이런 식으로 함수를 한번만 만들어 놓고 갖다쓰면 매우 편리합니다.

<?
//include_once(dirname(__FILE__)."/common.php");

include_once(dirname(__FILE__)."/crayMongo.php");
$manager = new MongoDB\Driver\Manager();
$count = crayMongoCount($manager, "craydb", "book", ['author' => 'cray']);
echo $count."건";

필요하신 분에게 도움이 되셨을지요? :)
크레이도 공부하고 필요하신 분께도 공유해 드리고 일석 이조!

오늘도 여기까지 읽어주셔서 감사합니다.


하나님의 말씀을 마음에 담아두면 영혼의 양식에 큰 도움이 됩니다.

주께서 호령과 천사장의 소리와 하나님의 나팔로 친히 하늘로 좇아 강림하시리니 
그리스도안에서 죽은 자들이 먼저 일어나고 
그 후에 우리 살아 남은 자도 저희와 함께 구름 속으로 끌어 올려 공중에서 주를 영접하게 하시리니 
그리하여 우리가 항상 주와 함께 있으리라

- 데살로니가 전서 4장 16,17절 말씀 -