我正在学习DocumentDb中的数据建模。这是我需要一些建议的地方
请在下面查看我的文档。
在这里我可以采取两种方法,各有利弊。
方案1:
如果我通过将项目团队成员信息(例如名字,姓氏,电子邮件等)保留在与项目相同的文件中来保持数据的非规范化(请参阅下面的文档),则当Jane Doe可以在一个查询中获得所需的信息结婚并更改了她的姓氏后,我将不得不更新Projects集合中的许多文档。我还必须非常小心,以确保所有包含员工信息的文档集合也要更新。例如,如果我在Projects集合中更新了Jane Doe的名字,却忘了更新TimeSheets集合,那我就麻烦了!
方案2:
如果我在某种程度上使数据标准化,并且在项目文档中仅保留EmployeeId,那么我每当想要获得项目列表时都可以运行三个查询:
然后,我可以合并应用程序中的所有数据。
这里的问题是DocumentDb现在似乎有很多限制。我可能正在阅读数百个项目团队中有数百名员工的项目。似乎没有一种有效的方法来获取其ID出现在第二个查询中的所有员工信息。同样,请记住,我可能需要在此处提取数百个员工信息。如果以下SQL查询是我要用于员工数据的查询,则可能必须运行几次相同的查询才能获取所需的所有信息,因为我认为我无法拥有数百个OR语句:
SELECT e.Id, e.firstName, e.lastName, e.emailAddress
FROM Employees e
WHERE e.Id = 1111 OR e.Id = 2222
我知道DocumentDb仍在预览中,其中一些限制将得到修复。话虽如此,我应该如何解决这个问题?如何有效地存储/管理和检索我需要的所有项目数据-包括项目团队信息?方案1是更好的解决方案还是方案2,还是有更好的第三选择?
这是我的文档的样子。一,项目文件:
{
id: 789,
projectName: "My first project",
startDate: "9/6/2014",
projectTeam: [
{ id: 1111, firstName: "John", lastName: "Smith", position: "Sr. Engineer" },
{ id: 2222, firstName: "Jane", lastName: "Doe", position: "Project Manager" }
]
}
这是雇员集合中的两个雇员文档:
{
id: 1111,
firstName: "John",
lastName: "Smith",
dateOfBirth: "1/1/1967',
emailAddresses: [
{ email: "[email protected]", isPrimary: "true" },
{ email: "[email protected]", isPrimary: "false" }
]
},
{
id: 2222,
firstName: "Jane",
lastName: "Doe",
dateOfBirth: "3/8/1975',
emailAddresses: [
{ email: "[email protected]", isPrimary: "true" }
]
}
我相信您在考虑对项目和员工数据进行规范化或反规范化之间的权衡是正确的。如前所述:
场景1)如果您对数据模型进行非规范化(将项目和员工数据耦合在一起)-您可能会发现自己在更新员工时必须更新许多项目。
方案2)如果规范化数据模型(将项目和员工数据分离)-如果要获取属于项目的员工列表,则必须查询项目以检索employeeId,然后查询员工。
考虑到您的应用程序的用例,我会选择适当的权衡。通常,当您有大量读取应用程序时,我更喜欢取消规范化;如果有大量写入应用程序,则我更喜欢进行标准化。
请注意,您可以通过利用DocumentDB的存储过程来避免在应用程序和数据库之间进行多次往返(查询将在DocumentDB服务器端执行)。
这是一个用于检索属于特定projectId的员工的示例存储过程:
function(projectId) {
/* the context method can be accessed inside stored procedures and triggers*/
var context = getContext();
/* access all database operations - CRUD, query against documents in the current collection */
var collection = context.getCollection();
/* access HTTP response body and headers from the procedure */
var response = context.getResponse();
/* Callback for processing query on projectId */
var projectHandler = function(documents) {
var i;
for (i = 0; i < documents[0].projectTeam.length; i++) {
// Query for the Employees
queryOnId(documents[0].projectTeam[i].id, employeeHandler);
}
};
/* Callback for processing query on employeeId */
var employeeHandler = function(documents) {
response.setBody(response.getBody() + JSON.stringify(documents[0]));
};
/* Query on a single id and call back */
var queryOnId = function(id, callbackHandler) {
collection.queryDocuments(collection.getSelfLink(),
'SELECT * FROM c WHERE c.id = \"' + id + '\"', {},
function(err, documents) {
if (err) {
throw new Error('Error' + err.message);
}
if (documents.length < 1) {
throw 'Unable to find id';
}
callbackHandler(documents);
}
);
};
// Query on the projectId
queryOnId(projectId, projectHandler);
}
即使DocumentDB在预览期间支持有限的OR语句,您仍然可以通过将employeeId查找分为多个异步服务器端查询来获得相对较好的性能。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句