문서 메뉴

문서 홈Atlas App Services

획기적인 스키마 변경

이 페이지의 내용

  • 개요
  • 파트너 컬렉션
  • 절차
  • 애그리게이션 파이프라인을 사용하여 파트너 컬렉션 초기화
  • 파트너 컬렉션을 위한 데이터베이스 트리거 설정
  • 트리거 함수 추가
  • 개발 모드 및 단절적 변경

Atlas Device Sync에서 사용되는 객체 스키마를 변경해야 하는 경우 추가 작업 없이 손상적이지 않은 변경 사항을 적용할 수 있습니다. 그러나 손상적인 변경 사항에는 추가적인 단계가 필요합니다. 손상적이거나 파괴적인 변경에는 기존 필드의 이름을 바꾸거나 필드의 데이터 유형을 변경하는 것이 포함됩니다.

자세한 내용은 데이터 모델 업데이트를 참조하세요.

손상적인 스키마 변경을 수행해야 하는 경우 다음 두 가지 선택이 있습니다.

  • 백엔드에서 동기화를 종료한 다음 처음부터 다시 동기화를 활성화합니다.

  • 파트너 컬렉션 을 만들고 이전 데이터를 이 새 컬렉션에 복사한 다음 트리거를 설정하여 데이터 일관성을 보장합니다.

    이 가이드의 나머지 부분에서는 파트너 컬렉션을 만드는 방법을 안내합니다.

경고

동기화 종료 후 동기화 복원하기

Atlas Device Sync를 종료했다가 다시 허용하면 클라이언트가 더 이상 동기화할 수 없습니다. 동기화를 복원하려면 클라이언트가 클라이언트 재설정 핸들러를 구현해야 합니다. 이 핸들러는 동기화되지 않은 변경 사항을 삭제하거나 복구를 시도할 수 있습니다.

다음 절차에서 초기 컬렉션은 Task 컬렉션에 아래 JSON 스키마를 사용합니다. Task의 스키마에는 objectId 유형의 _id 필드가 포함되어 있습니다:

작업 스키마
{
"title": "Task",
"bsonType": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "objectId"
},
"_partition": {
"bsonType": "string"
},
"name": {
"bsonType": "string"
}
}
}

스키마는 _id 필드를 문자열로 구성한다는 점을 제외하면 동일합니다.

작업 스키마
{
"title": "Task",
"bsonType": "object",
"required": [
"_id",
"name"
],
"properties": {
"_id": {
"bsonType": "string"
},
"_partition": {
"bsonType": "string"
},
"name": {
"bsonType": "string"
}
}
}
1

손상적인 변경 사항은 동기화된 객체 스키마에서 직접 수행할 수 없으므로 필요한 변경 사항이 포함된 스키마를 사용하여 파트너 컬렉션을 만들어야 합니다. 최신 클라이언트가 이전 클라이언트와 동기화할 수 있도록 파트너 컬렉션에 원본 컬렉션과 동일한 데이터가 있는지 확인해야 합니다.

원본 컬렉션에서 새 파트너 컬렉션으로 데이터를 복사하는 데 권장되는 접근 방식은 애그리게이션 프레임워크를 사용하는 것입니다.

/aggregation-pipeline-builder/ 또는 /data-explorer/cloud-agg-pipeline/ 을 사용하여 mongo 셸에서 집계 파이프라인을 만들고 실행할 수 있습니다.

파이프라인은 다음과 같은 단계로 구성됩니다:

  1. $match 연산자에 빈 필터를 전달하여 초기 컬렉션의 모든 문서를 일치시킵니다.

  2. 집계 파이프라인 연산자 를 사용하여 초기 컬렉션의 필드를 수정합니다. 다음 예제에서는 $addFields 연산자 를 사용하여 데이터를 변환합니다. _id 필드는 $toString 연산자를 사용하여 string 유형으로 변환됩니다.

  3. $out 연산자 를 사용하고 파트너 컬렉션 이름을 지정하여 변환된 데이터를 파트너 컬렉션에 씁니다. 이 예제에서는 TaskV2 이라는 새 컬렉션에 데이터를 씁니다.

여기에는 Atlas 및 Compass UI에 표시된 것과 동일한 파이프라인이 있습니다. 이 두 도구는 모두 변경 사항의 미리 보기를 제공하며, 이 경우 _id 필드를 ObjectId에서 문자열로 변환합니다:

애그리게이션 빌더용 Atlas UI

다음 예제에서는 mongosh 를 사용하여 변환을 수행한 경우의 전체 집계 파이프라인을 보여 줍니다.

초기 컬렉션의 모든 문서를 일치시켜 파트너 컬렉션으로 출력
use "<database-name>" // switch the current db to the db that the Task collection is stored in
collection = db.Task;
collection.aggregate([
{ $match: {} }, // match all documents in the Task collection
{
$addFields: { // transform the data
_id: { $toString: "$_id" }, // change the _id field of the data to a string type
},
},
{ $out: "TaskV2" }, // output the data to a partner collection, TaskV2
]);
2

파트너 컬렉션이 설정되면 이를 사용하여 기존 데이터를 읽을 수 있습니다. 그러나 한 컬렉션 데이터에 대한 새로운 쓰기 작업은 다른 컬렉션에 적용되지 않습니다. 이로 인해 기존 클라이언트가 새 클라이언트와 동기화되지 않습니다.

데이터가 두 컬렉션에 모두 반영되도록 하려면 각 컬렉션에서 데이터베이스 트리거를 설정합니다. 데이터가 한 컬렉션에 기록되면 트리거의 함수는 파트너 컬렉션에 쓰기를 수행합니다.

데이터베이스 트리거 설명서의 단계에 따라 모든 작업 유형에 대해 Task 컬렉션에서 TaskV2 컬렉션으로 데이터를 복사하는 트리거를 만듭니다. 이 단계를 반복하여 TaskV2 컬렉션에서 Task 컬렉션으로 데이터를 복사하는 두 번째 트리거를 만듭니다.

3

트리거에는 트리거가 실행될 때 실행되는 지원 함수가 필요합니다. 이 경우 순방향 마이그레이션 함수와 역방향 마이그레이션 함수, 이렇게 두 가지 함수를 만들어야 합니다.

순방향 마이그레이션 트리거는 Task 컬렉션에서 삽입, 업데이트 및 삭제를 수신하고 TaskV2 컬렉션의 스키마를 반영하도록 수정한 다음 TaskV2 컬렉션에 적용합니다.

TaskV2 컬렉션의 변경 사항을 수신하고 이를 Task 컬렉션에 적용하려면 TaskV2 컬렉션의 트리거에 대한 역방향 마이그레이션 함수를 작성합니다. 역방향 마이그레이션은 이전 단계와 동일한 아이디어를 따릅니다.

정방향2 Delete 에서는 어떤 작업이 함수를 트리거했는지 확인합니다. 작업 유형이 Write (삽입 또는 수정) 이벤트인 경우 집계 파이프라인이 생성됩니다. 파이프라인에서 Task 컬렉션에 삽입되거나 수정된 문서는 $match 연산자 를 사용하여 추출됩니다. 그런 다음 추출된 문서는 TaskV2 컬렉션의 스키마를 준수하도록 변환됩니다. 마지막으로 $merge 연산자를 사용하여 변환된 데이터를 TaskV2 컬렉션에 기록합니다.

copyTaskObjectToTaskV2 함수
exports = function (changeEvent) {
const db = context.services.get("mongodb-atlas").db("ExampleDB");
const collection = db.collection("Task");
// If the event type is "invalidate", the next const throws an error.
// Return early to avoid this.
if (!changeEvent.documentKey) { return; }
// The changed document's _id as an integer:
const changedDocId = changeEvent.documentKey._id;
// If a document in the Task collection has been deleted,
// delete the equivalent object in the TaskV2 collection:
if (changeEvent.operationType === "delete") {
const tasksV2Collection = db.collection("TaskV2");
// Convert the deleted document's _id to a string value
// to match TaskV2's schema:
const deletedDocumentID = changedDocId.toString();
return tasksV2Collection.deleteOne({ _id: deletedDocumentID })
}
// A document in the Task collection has been created,
// modified, or replaced, so create a pipeline to handle the change:
const pipeline = [
// Find the changed document data in the Task collection:
{ $match: { _id: changeEvent.documentKey._id } },
{
// Transform the document by changing the _id field to a string:
$addFields: {
_id: { $toString: "$_id" },
},
},
// Insert the document into TaskV2, using the $merge operator
// to avoid overwriting the existing data in TaskV2:
{ $merge: "TaskV2" }]
return collection.aggregate(pipeline);
};

역방향 마이그레이션 함수는 이전 단계의 예와 유사한 단계를 거칩니다. 한 컬렉션에서 문서가 삭제되면 다른 컬렉션에서도 해당 문서가 삭제됩니다. 작업 유형이 쓰기 이벤트인 경우 TaskV2 에서 변경된 문서가 추출되고 Task 컬렉션의 스키마와 일치하도록 변환되며 Task 컬렉션에 기록됩니다.

copyTaskV2ObjectToTask 함수
exports = function (changeEvent) {
const db = context.services.get("mongodb-atlas").db("ExampleDB");
const collection = db.collection("TaskV2");
// If the event type is "invalidate", the next const throws an error.
// Return early to avoid this.
if (!changeEvent.documentKey) { return; }
// The changed document's _id as a string:
const changedDocId = changeEvent.documentKey._id;
// If a document in the TaskV2 collection has been deleted,
// delete the equivalent object in the Task collection
if (changeEvent.operationType === "delete") {
const taskCollection = db.collection("Task");
// Convert the deleted document's _id to an integer value
// to match Task's schema:
const deletedDocumentID = parseInt(changedDocId);
return taskCollection.deleteOne({ _id: deletedDocumentID })
}
// A document in the Task collection has been created,
// modified, or replaced, so create a pipeline to handle the change:
const pipeline = [
// Find the changed document data in the Task collection
{ $match: { _id: changedDocId } },
{
// Transform the document by changing the _id field
$addFields: {
_id: { $toInt: "$_id" },
},
},
{ $merge: "Task" }
]
return collection.aggregate(pipeline);
};

2023년 9월 13일 이후에 만든 App Services 앱에 적용됩니다.

2023년 9월 13일 이후에 생성된 개발 모드의 App Services 앱은 클라이언트 코드에서 동기화된 객체 스키마로 손상적인 변경 사항을 적용할 수 있습니다.

개발 모드에서 변경 사항을 적용하는 방법에 대한 자세한 내용은 개발 모드를 참조하세요.

개발 모드는 프로덕션용으로 사용하기에 적합하지 않습니다. 개발 모드를 사용하는 경우 앱을 프로덕션 환경으로 이동하기 전에 해당 모드를 비활성화해야 합니다.

← 데이터 모델 업데이트