DocumentDB - การสร้างแบบจำลองข้อมูล
แม้ว่าฐานข้อมูลที่ไม่มีสคีมาเช่น DocumentDB จะทำให้การเปลี่ยนแปลงโมเดลข้อมูลของคุณเป็นเรื่องง่ายมาก แต่คุณควรใช้เวลาคิดเกี่ยวกับข้อมูลของคุณ
คุณมีตัวเลือกมากมาย โดยปกติคุณสามารถทำงานกราฟออบเจ็กต์ JSON หรือแม้กระทั่งสตริงดิบของข้อความ JSON แต่คุณยังสามารถใช้วัตถุแบบไดนามิกที่ช่วยให้คุณเชื่อมโยงกับคุณสมบัติในรันไทม์ได้โดยไม่ต้องกำหนดคลาสในเวลาคอมไพล์
คุณยังสามารถทำงานกับออบเจ็กต์ C # จริงหรือเอนทิตีตามที่เรียกซึ่งอาจเป็นคลาสโดเมนธุรกิจของคุณ
ความสัมพันธ์
มาดูโครงสร้างลำดับชั้นของเอกสารกัน มีคุณสมบัติระดับบนสุดสองสามอย่างเช่นรหัสที่ต้องการเช่นเดียวกับ lastName และ isRegistered แต่ก็มีคุณสมบัติที่ซ้อนกัน
{
"id": "AndersenFamily",
"lastName": "Andersen",
"parents": [
{ "firstName": "Thomas", "relationship": "father" },
{ "firstName": "Mary Kay", "relationship": "mother" }
],
"children": [
{
"firstName": "Henriette Thaulow",
"gender": "female",
"grade": 5,
"pets": [ { "givenName": "Fluffy", "type": "Rabbit" } ]
}
],
"location": { "state": "WA", "county": "King", "city": "Seattle"},
"isRegistered": true
}
ตัวอย่างเช่นคุณสมบัติ parent ถูกจัดให้เป็นอาร์เรย์ JSON ตามที่แสดงโดยวงเล็บเหลี่ยม
นอกจากนี้เรายังมีอาร์เรย์อื่นสำหรับเด็กแม้ว่าจะมีลูกเดียวในอาร์เรย์ในตัวอย่างนี้ นี่คือวิธีที่คุณสร้างโมเดลให้เทียบเท่ากับความสัมพันธ์แบบหนึ่งต่อกลุ่มภายในเอกสาร
คุณเพียงแค่ใช้อาร์เรย์โดยที่แต่ละองค์ประกอบในอาร์เรย์อาจเป็นค่าธรรมดาหรือวัตถุที่ซับซ้อนอื่นแม้แต่อาร์เรย์อื่น
ดังนั้นครอบครัวหนึ่งสามารถมีพ่อแม่หลายคนและมีลูกได้หลายคนและหากคุณมองไปที่วัตถุของเด็กพวกเขาจะมีทรัพย์สินของสัตว์เลี้ยงซึ่งเป็นอาร์เรย์ที่ซ้อนกันสำหรับความสัมพันธ์ระหว่างเด็กและสัตว์เลี้ยง
สำหรับคุณสมบัติตำแหน่งเรากำลังรวมคุณสมบัติที่เกี่ยวข้องสามอย่างรัฐเขตและเมืองไว้ในวัตถุ
การฝังวัตถุด้วยวิธีนี้แทนที่จะฝังอาร์เรย์ของวัตถุคล้ายกับการมีความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่างสองแถวในตารางแยกกันในฐานข้อมูลเชิงสัมพันธ์
การฝังข้อมูล
เมื่อคุณเริ่มสร้างโมเดลข้อมูลในที่เก็บเอกสารเช่น DocumentDB ให้พยายามปฏิบัติต่อเอนทิตีของคุณเป็นเอกสารที่มีอยู่ในตัวซึ่งแสดงใน JSON เมื่อทำงานกับฐานข้อมูลเชิงสัมพันธ์เราจะทำให้ข้อมูลเป็นมาตรฐานเสมอ
โดยทั่วไปการทำให้ข้อมูลของคุณเป็นปกติจะเกี่ยวข้องกับการพิจารณาเอนทิตีเช่นลูกค้าและแยกย่อยออกเป็นส่วนข้อมูลที่รอบคอบเช่นรายละเอียดการติดต่อและที่อยู่
ในการอ่านลูกค้าพร้อมรายละเอียดการติดต่อและที่อยู่ทั้งหมดคุณต้องใช้ JOINS เพื่อรวบรวมข้อมูลของคุณอย่างมีประสิทธิภาพในขณะดำเนินการ
ตอนนี้เรามาดูวิธีที่เราจะสร้างแบบจำลองข้อมูลเดียวกันกับเอนทิตีที่มีอยู่ในตัวเองในฐานข้อมูลเอกสาร
{
"id": "1",
"firstName": "Mark",
"lastName": "Upston",
"addresses": [
{
"line1": "232 Main Street",
"line2": "Unit 1",
"city": "Brooklyn",
"state": "NY",
"zip": 11229
}
],
"contactDetails": [
{"email": "[email protected]"},
{"phone": "+1 356 545-86455", "extension": 5555}
]
}
ดังที่คุณเห็นว่าเราได้ทำให้บันทึกของลูกค้าผิดปกติโดยที่ข้อมูลทั้งหมดของลูกค้าถูกฝังอยู่ในเอกสาร JSON เดียว
ใน NoSQL เรามีสคีมาฟรีดังนั้นคุณสามารถเพิ่มรายละเอียดการติดต่อและที่อยู่ในรูปแบบต่างๆได้เช่นกัน ใน NoSQL คุณสามารถดึงข้อมูลลูกค้าจากฐานข้อมูลได้ในการดำเนินการอ่านครั้งเดียว ในทำนองเดียวกันการอัปเดตเรกคอร์ดยังเป็นการดำเนินการเขียนเพียงครั้งเดียว
ต่อไปนี้เป็นขั้นตอนในการสร้างเอกสารโดยใช้. Net SDK
Step 1- สร้างอินสแตนซ์ DocumentClient จากนั้นเราจะค้นหาฐานข้อมูล myfirstdb และค้นหาคอลเล็กชัน MyCollection ซึ่งเราเก็บไว้ในคอลเล็กชันตัวแปรส่วนตัวนี้เพื่อให้สามารถเข้าถึงได้ทั่วทั้งชั้นเรียน
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
await CreateDocuments(client);
}
}
Step 2 - สร้างเอกสารบางอย่างในงาน CreateDocuments
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
dynamic document1Definition = new {
name = "New Customer 1", address = new {
addressType = "Main Office",
addressLine1 = "123 Main Street",
location = new {
city = "Brooklyn", stateProvinceName = "New York"
},
postalCode = "11229", countryRegionName = "United States"
},
};
Document document1 = await CreateDocument(client, document1Definition);
Console.WriteLine("Created document {0} from dynamic object", document1.Id);
Console.WriteLine();
}
เอกสารแรกจะถูกสร้างขึ้นจากวัตถุไดนามิกนี้ สิ่งนี้อาจดูเหมือน JSON แต่แน่นอนว่าไม่ใช่ นี่คือรหัส C # และเรากำลังสร้างออบเจ็กต์. NET จริง แต่ไม่มีนิยามคลาส แต่คุณสมบัติจะถูกอนุมานจากวิธีเริ่มต้นวัตถุ คุณสามารถสังเกตได้ว่าเราไม่ได้ให้คุณสมบัติ Id สำหรับเอกสารนี้
Step 3 - ตอนนี้เรามาดู CreateDocument และดูเหมือนว่าจะเป็นรูปแบบเดียวกับที่เราเห็นในการสร้างฐานข้อมูลและคอลเล็กชัน
private async static Task<Document> CreateDocument(DocumentClient client,
object documentObject) {
var result = await client.CreateDocumentAsync(collection.SelfLink, documentObject);
var document = result.Resource;
Console.WriteLine("Created new document: {0}\r\n{1}", document.Id, document);
return result;
}
Step 4- คราวนี้เราเรียก CreateDocumentAsync ระบุ SelfLink ของคอลเล็กชันที่เราต้องการเพิ่มเอกสาร เราได้รับการตอบกลับพร้อมคุณสมบัติทรัพยากรที่ในกรณีนี้แสดงถึงเอกสารใหม่ที่มีคุณสมบัติที่ระบบสร้างขึ้น
ในงาน CreateDocuments ต่อไปนี้เราได้สร้างเอกสารสามชุด
ในเอกสารแรกอ็อบเจ็กต์ Document เป็นคลาสที่กำหนดไว้ใน SDK ซึ่งสืบทอดมาจากรีซอร์สดังนั้นจึงมีคุณสมบัติรีซอร์สทั่วไปทั้งหมด แต่ยังรวมคุณสมบัติไดนามิกที่กำหนดเอกสารที่ไม่มีสคีมาด้วย
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
dynamic document1Definition = new {
name = "New Customer 1", address = new {
addressType = "Main Office",
addressLine1 = "123 Main Street",
location = new {
city = "Brooklyn", stateProvinceName = "New York"
},
postalCode = "11229",
countryRegionName = "United States"
},
};
Document document1 = await CreateDocument(client, document1Definition);
Console.WriteLine("Created document {0} from dynamic object", document1.Id);
Console.WriteLine();
var document2Definition = @" {
""name"": ""New Customer 2"",
""address"": {
""addressType"": ""Main Office"",
""addressLine1"": ""123 Main Street"",
""location"": {
""city"": ""Brooklyn"", ""stateProvinceName"": ""New York""
},
""postalCode"": ""11229"",
""countryRegionName"": ""United States""
}
}";
Document document2 = await CreateDocument(client, document2Definition);
Console.WriteLine("Created document {0} from JSON string", document2.Id);
Console.WriteLine();
var document3Definition = new Customer {
Name = "New Customer 3",
Address = new Address {
AddressType = "Main Office",
AddressLine1 = "123 Main Street",
Location = new Location {
City = "Brooklyn", StateProvinceName = "New York"
},
PostalCode = "11229",
CountryRegionName = "United States"
},
};
Document document3 = await CreateDocument(client, document3Definition);
Console.WriteLine("Created document {0} from typed object", document3.Id);
Console.WriteLine();
}
เอกสารที่สองนี้ใช้ได้กับสตริง JSON ดิบ ตอนนี้เราก้าวเข้าสู่การโอเวอร์โหลดสำหรับ CreateDocument ที่ใช้ JavaScriptSerializer เพื่อยกเลิกการต่ออนุกรมสตริงลงในอ็อบเจ็กต์ซึ่งจะส่งต่อไปยังเมธอด CreateDocument เดียวกับที่เราใช้ในการสร้างเอกสารแรก
ในเอกสารฉบับที่สามเราได้ใช้วัตถุ C # ลูกค้าซึ่งกำหนดไว้ในใบสมัครของเรา
ลองมาดูที่ลูกค้ารายนี้มีคุณสมบัติ Id และ address โดยที่อยู่เป็นอ็อบเจ็กต์ที่ซ้อนกันซึ่งมีคุณสมบัติของตัวเองรวมถึงตำแหน่งซึ่งเป็นอีกอ็อบเจกต์ที่ซ้อนกัน
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DocumentDBDemo {
public class Customer {
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
// Must be nullable, unless generating unique values for new customers on client
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "address")]
public Address Address { get; set; }
}
public class Address {
[JsonProperty(PropertyName = "addressType")]
public string AddressType { get; set; }
[JsonProperty(PropertyName = "addressLine1")]
public string AddressLine1 { get; set; }
[JsonProperty(PropertyName = "location")]
public Location Location { get; set; }
[JsonProperty(PropertyName = "postalCode")]
public string PostalCode { get; set; }
[JsonProperty(PropertyName = "countryRegionName")]
public string CountryRegionName { get; set; }
}
public class Location {
[JsonProperty(PropertyName = "city")]
public string City { get; set; }
[JsonProperty(PropertyName = "stateProvinceName")]
public string StateProvinceName { get; set; }
}
}
นอกจากนี้เรายังมีแอตทริบิวต์คุณสมบัติ JSON เนื่องจากเราต้องการคงรูปแบบที่เหมาะสมไว้ทั้งสองด้านของรั้ว
ดังนั้นฉันจึงสร้างอ็อบเจ็กต์ New Customer ของฉันพร้อมกับอ็อบเจ็กต์ลูกที่ซ้อนกันและโทรเข้า CreateDocument อีกครั้ง แม้ว่าออบเจ็กต์ลูกค้าของเราจะมีคุณสมบัติ Id แต่เราก็ไม่ได้ให้ค่าสำหรับมันดังนั้น DocumentDB จึงสร้างขึ้นมาตาม GUID เช่นเดียวกับที่ทำกับเอกสารสองชุดก่อนหน้า
เมื่อโค้ดด้านบนถูกคอมไพล์และดำเนินการคุณจะได้รับผลลัพธ์ต่อไปนี้
**** Create Documents ****
Created new document: 575882f0-236c-4c3d-81b9-d27780206b2c
{
"name": "New Customer 1",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
"id": "575882f0-236c-4c3d-81b9-d27780206b2c",
"_rid": "kV5oANVXnwDGPgAAAAAAAA==",
"_ts": 1450037545,
"_self": "dbs/kV5oAA==/colls/kV5oANVXnwA=/docs/kV5oANVXnwDGPgAAAAAAAA==/",
"_etag": "\"00006fce-0000-0000-0000-566dd1290000\"",
"_attachments": "attachments/"
}
Created document 575882f0-236c-4c3d-81b9-d27780206b2c from dynamic object
Created new document: 8d7ad239-2148-4fab-901b-17a85d331056
{
"name": "New Customer 2",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
"id": "8d7ad239-2148-4fab-901b-17a85d331056",
"_rid": "kV5oANVXnwDHPgAAAAAAAA==",
"_ts": 1450037545,
"_self": "dbs/kV5oAA==/colls/kV5oANVXnwA=/docs/kV5oANVXnwDHPgAAAAAAAA==/",
"_etag": "\"000070ce-0000-0000-0000-566dd1290000\"",
"_attachments": "attachments/"
}
Created document 8d7ad239-2148-4fab-901b-17a85d331056 from JSON string
Created new document: 49f399a8-80c9-4844-ac28-cd1dee689968
{
"id": "49f399a8-80c9-4844-ac28-cd1dee689968",
"name": "New Customer 3",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
"_rid": "kV5oANVXnwDIPgAAAAAAAA==",
"_ts": 1450037546,
"_self": "dbs/kV5oAA==/colls/kV5oANVXnwA=/docs/kV5oANVXnwDIPgAAAAAAAA==/",
"_etag": "\"000071ce-0000-0000-0000-566dd12a0000\"",
"_attachments": "attachments/"
}
Created document 49f399a8-80c9-4844-ac28-cd1dee689968 from typed object