본문 바로가기
코딩과 알고리즘

PHP + 몽고DB 크루드! ( CRUD )

'크루드'하면 웬지 "딴-- 따라다~' 배경음악이 등장하는
미션 임파서블'의 '톰 크루즈'가 생각이 납니다 :)

톰 크루즈는 불운한 어린 시절을 보냈지만 이를 극복하고
결국 멋진 연기 인생을 꽃 피우게 되지요.

하지만 단순히 운이라고 할 수 없을만한,
많은 팬들에게 사랑받는 힘은 가히 말로 설명할 수 없는
'이른바 목숨을 건 연기' 의 힘이 크다고도 합니다.

스턴트맨 없이 안전와이어도 없이 직접 암벽 등반을 해내거나
세계에서 가장 높은 부르즈 할리파라는 빌딩에서 뛰어내리는 액션을 해내는
그 밖에도 톰크루즈 주연의 여러 액션 영화에서 기막히고 위험한 액션들은
톰 크루즈가 직접 해낸 것이라고 합니다.

관객들은 정말 이 겂없는 배우의 연기에 집중하는 것보다도,
'임파서블한 미션'에 집중하는 것이 더 크지는 않나 생각이 드네요 :)

하여간, 오늘 말씀드릴 크루드는 이 톰 크루즈와는 사실 관련이 없습니다.
그냥 머리 환기 시켜드리려고 꺼내든 이야기입니다 :D :D :D

크루드는 영어로 CRUD 인데,
Create(만들고), Read(읽고), Update(고치고), Delete(지우는) 4개 단어의
각각 알파벳 영어의 앞글자를 따서 CRUD 라고 지칭하는 것이지요.

관계형 데이터 베이스든 NoSQL 데이터베이스든간에 모든 데이터베이스의 기본 동작은 CRUD 입니다.
몽고 DB도 예외일 수가 없지요.
오늘은 지난번 PHP 에서 보안 기능 활성화 모드의 몽고 DB 접속편에 이어,

itadventure.tistory.com/382

 

보안기능활성화 모드의 PHP + 몽고DB

지난 시간에는 몽고DB에서의 관리자 계정 설정에 대해서 다루어 보았습니다. itadventure.tistory.com/381 몽고DB, 데이터베이스별 관리자 계정 생성 이번 시간에는 지난번의 몽고 DB 최고관리자 계정 생

itadventure.tistory.com

mongo.so 모듈의 기본 클래스 Manager 를 이용하여 CRUD 액션을 수행하는 방법을 살펴보겠습니다.

첫번째 동작은 생성(Create), 곧 삽입(Insert)입니다.
삽입 동작은 기본적으로 아래 코드를 따릅니다.

$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert( 도큐먼트배열 );
$bulk->insert( 도큐먼트배열 );
$bulk->insert( 도큐먼트배열 );
$result = $manager->executeBulkWrite('데이터베이스.컬렉션', $bulk);
// $result->getInsertedCount(); // 기록된 갯수

벌크쓰기(BulkWrite)라는 개념이 새로 나왔네요?
벌크쓰기 역시 mongo.so 에서 기본 제공하는 클래스인데요.

여기서는 대량쓰기라는 개념으로 이해하시면 됩니다.

코드의 해석은 아래와 같은데요.
먼저 벌트쓰기 세트를 마련한 다음,

$bulk = new MongoDB\Driver\BulkWrite;

아래와 같이 기록할 데이터를 쭉 마련합니다
아직은 몽고 DB에 쓰기를 한 것이 아니기 때문에,
이대로 종료하면 아무것도 기록되지 않고 끝나 버립니다.

$bulk->insert( 도큐먼트배열 );
$bulk->insert( 도큐먼트배열 );
  :
  :

그리고 지정한 데이터베이스의 컬렉션에 준비된 벌크쓰기 세트를 적용하는 것이지요,
이 때 실제로 몽고DB에 데이터를 기록하게 됩니다.
그리고 그 결과를 $result 변수에 받아오는 것입니다.

$result = $manager->executeBulkWrite('데이터베이스.컬렉션', $bulk);

벌크세트로 수행한 모든 동작은 100% 실행되었다고 보장할수는 없는데요.
데이터가 오류가 있거나 어떤 사연에 의해서 일부 데이터만 삽입되었을 수 있기 때문입니다.

그래서 여기서 실제 삽입된 갯수를 알아내려면 반환된 $result 를 확인해야 합니다.
$result 또한 클래스 객체이며 아래 메소드로 실제 삽입된 갯수를 알아낼 수 있습니다.

$result->getInsertedCount();

개념적으로만 설명드리면 약간 혼선이 올 수 있어 아래와 같은 예제를 준비했는데요.
아래 소스를 /usr/share/nginx/html 폴더특정페이지이름.php 으로 저장하신 다음,
AWS의 퍼블릭URL/특정페이지이름.php 로 접근하시면 실행됩니다.
패스워드는 당연히 수정해주셔야겠지요?

<?php
$manager = new MongoDB\Driver\Manager("mongodb://uadmin:패스워드@localhost:27017/crayUniversity");

$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert( ['code' => '10004', 'name' => '전산회계'] );
$result = $manager->executeBulkWrite('crayUniversity.department', $bulk);
echo "삽입된 갯수 : ".$result->getInsertedCount();
?>

 

이 예제는 crayUniversity 데이터베이스의 department 컬렉션에 학과코드 10004, '전산회계' 학과를 하나 추가해 줍니다.
그리고 삽입된 갯수를 알려줍니다.
독자분께서 데이터베이스 이름을 다르게 하셨다면 이름과 속성을 다르게 주셔서 한번 테스트 해보세요.

삽입된 갯수 : 1

제대로 데이터가 들어갔을까요?
AWS 의 콘솔이든 모바XTERM 이든 편리하신 방법으로 접속하여 확인해보도록 합시다.

리눅스 콘솔 창에서 몽고 DB 콘솔에 접속하여

mongo -u DB관리자계정 접속권한DB명

컬렉션의 자료를 확인해 봅시다.

db.department.find().pretty()
           :
{
        "_id" : ObjectId("5fcb0694af460d38fa164fd1"),
        "code" : "10004",
        "name" : "전산회계"
}
>

제대로 자료가 입력되었군요. 만일 이 소스를 한번 더 실행해 봅시다.
방금 전의 웹페이지를 한번 더 실행하시면 되는데요.
실행 후 다시 한번 컬렉션의 내용을 확인해보면,

db.department.find().pretty()

2건의 자료가 중복 입력된 것을 확인할 수 있습니다.
왜 그럴까요? 그것은 code 라는 항목이 유일하게 하나만 있어야 한다는 것을
알려주지 않았기 떄문입니다.,
그리고 그러고자 할 경우 삽입 동작이 아닌, 수정(Update) 동작을 수행해야 합니다.

{
        "_id" : ObjectId("5fc906af89990e67b800f04e"),
        "code" : "10004",
        "name" : "전산회계"
}
{
        "_id" : ObjectId("5fcb0694af460d38fa164fd1"),
        "code" : "10004",
        "name" : "전산회계"
}
>

PHP 에서 몽고DB 수정 역시 BulkWrite 를 이용하는데요.
약간 순서가 다르긴 하지만 두번째로 수정(Update) 동작을 먼저 살펴봅시다.

수정 동작의 기본 사용법은 아래와 같습니다.

$bulk = new MongoDB\Driver\BulkWrite;
$bulk->update(
  ['조건항목' => 조건값],  // 필터
  ['$set' => ['수정할항목' => '수정할값', ... ]],
  [
    'multi' => true/false,
    'upsert' => true/false
  ]  
);
$result = $manager->executeBulkWrite('crayUniversity.department', $bulk);

먼저 수정하려면 어떤 걸 수정할지를 선택해야 하는데요.
update 메소드의 첫번째 파라미터인 조건항목에서 그 값을 결정합니다.

['조건항목' => 조건값]

그리고 두번쨰 파라미터에는 수정할 각각의 항목값을 정해주는데요.
'$set'이라는 파라미터를 기준으로 수정할 항목을 배열로 해서 한번 더 묶어 주어야 합니다.

['$set' => ['수정할항목' => '수정할값', ... ]]

왜 이런 번거로운 걸 넣었을까요?
이는 수정 동작에서 항목을 수정할 수도 있지만 특정항목을 삭제('$unset')하는 기능도 있고 특정항목의 값을 증가('$inc')하는 방법도 있기 때문입니다. 이를 한번의 동작으로 지시할 수 있는데 향후에 다뤄보도록 하겠습니다.
프로그래밍 감각이 좋으신 분은 위의 드린 힌트만으로 사용가능하실 것으로 예상됩니다 :)

주의할 것은 수정지시자인 '$set'을 작은 따옴표(')를 사용해야지, 겹 따옴표(")를 사용하면 안된다는 것입니다.
겹 따옴표 사용시 PHP 인터프리터가 $set 을 변수로 해석해 버려서 값을 치환해 버리기 때문이지요.

"$set" ( x )

세번째 파라미터에는 수정할 방법을 지시하는 것인데요.
multi 속성은 첫번째 파라미터의 조건에 해당하는 자료가 여러개가 있을 경우, 하나만 수정할지(false) 모두 수정할지(true)를 정해주는 것입니다. 기본값은 false 입니다.

'multi' => true/false,

그리고 upsert 속성은 아주 편리한 기능을 제공하는데요,
이 값을  true 로 설정하면 만일 조건에 해당하는 자료가 있으면 수정해주지만, 없을 경우 새로 생성해주게 됩니다.
반면 false ( 기본값 ) 인 경우 새로 생성은 하지 않습니다.

'upsert' => true/false

아래 소스코드는 금방입력된 학과코드 10004의 학과명을 모두 '전산회계2'로 변경해 줍니다.
페이지를 하나 구성하셔서 한번 실행해 보세요.

<?php
$manager = new MongoDB\Driver\Manager("mongodb://uadmin:패스워드@localhost:27017/crayUniversity");

$bulk = new MongoDB\Driver\BulkWrite;
$bulk->update(
  ['code' => '10004'],
  ['$set' => ['name' => '전산회계2']],
  ['multi' => true]
);
$result = $manager->executeBulkWrite('crayUniversity.department', $bulk);

이제 다음 동작을 살펴봅시다.  세번째, Delete 동작인데요.
이 또한 BulkWrite 를 사용합니다. 하여간 쓰기, 수정, 지우기 동작은 모두 BulkWrite 를 사용한다고 생각하시면 됩니다.

// 데이터 삭제
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->delete( ['조건항목' => '조건값'] );
$result = $manager->executeBulkWrite('DB명.컬렉션명', $bulk);
// $result->getDeletedCount(); // 삭제된 갯수

크레이는 학과코드 10004 학과를 편성하기로 결정했으나, 예산이 나오지 않아서
다시 학과를 지우려고 합니다. 아직 아무 교직원도 학생도 모집하지 않아서 지금이 바로 삭제하기가 적절한 시기입니다. ( 미소를 지어드리려고 하는 이야기입니다 :D )

이 때의 샘플코드는 아래와 같습니다.

<?php
$manager = new MongoDB\Driver\Manager("mongodb://uadmin:패스워드@localhost:27017/crayUniversity");

// 데이터 삭제
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->delete( ['code' => '10004'] );
$result = $manager->executeBulkWrite('crayUniversity.department', $bulk);
echo "삭제된 갯수 : ".$result->getDeletedCount(); // 삭제된 갯수

자, 마지막으로 네번째, 읽기( Read ) 동작을 다뤄보도록 하겠습니다.

읽기 동작은 유일하게 BulkWrite 를 사용하지 않는데요.
이는 데이터에 아무런 조작을 가하지 않기 때문입니다.

기본적인 사용법은 아래와 같습니다. 읽기는 사실상 검색 기능이라고 볼 수 있습니다.

$cursor = $manager->executeQuery(
  "DB명.컬렉션명", 
  new MongoDB\Driver\Query( 
    ['조건항목' => 조건값] 
  )
);
$rows = $cursor->toArray();
foreach($rows as $one)
{
  // $one->속성 사용;
}

10004학과가 삭제가 되었기 때문에 앞에서 10004 학과를 추가하는 소스를 한번 실행해주신 다음에,
아래 예제를 실행해 보세요.
이 예제는 학과코드가 10004인 자료를 검색해서 모두 보여주는 기능을 실행합니다.

<?php
$manager = new MongoDB\Driver\Manager("mongodb://uadmin:4321@localhost:패스워드/crayUniversity");

$cursor = $manager->executeQuery(
  "crayUniversity.department", 
  new MongoDB\Driver\Query( 
    ['code' => '10004'] 
  )
);
$rows = $cursor->toArray();
foreach($rows as $one)
{
  echo $one->code. " : " . $one->name . "<br/>";
}
?>

이 코드를 한줄씩 살펴보면 아래와 같습니다.

$manager->executeQuery() 메소드에서 쿼리를 실행하는데,

대상은 crayUniversity 데이터베이스의 department 컬렉션이고

"crayUniversity.department",

학과코드값이 10004인 자료만을 검색합니다.

new MongoDB\Driver\Query( 
  ['code' => '10004'] 
)

그리고 그 결과를 커서에 받아옵니다.

$cursor = $manager->executeQuery(

이 커서를 PHP에서 다루기 편하게 배열로 바꿔준 다음에,

$rows = $cursor->toArray();

각 배열 요소를 반복하면서, ( 이 때 $one 에는 매 반복 턴마다 각 배열 요소 1개의 값이 대입됩니다 )

foreach($rows as $one)

각 배열의 요소를 찍어줍니다.

echo $one->code. " : " . $one->name . "<br/>";

그래서 위 소스를 실행하면 이런 결과를 실행하지요. 자료를 여러번 입력한 경우 여러개의 자료가 나올 것입니다.

10004 : 전산회계

이상 PHP 에서 몽고DB의 4가지 CRUD 사용방법을 알아보았습니다.
아무쪼록 필요하신 분에게 도움이 되셨을지 모르겠습니다.

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


하나님의 말씀은 지혜의 근원입니다.

깊도다 하나님의 지혜와 지식의 부요함이여 그의 판단은 측량치 못할 것이며 그의 길은 찾지 못할 것이로다
- 로마서 11장 33절 말씀 -