我的应用程序中有两个实体-User
和Shift
。他们共享多对多关系。
这是我使用非规范化技术和4个顶级节点构造数据库的方式:
{
"shift-assign":{
"-Lwo52vuW9QqCmAfS90w":{
"111":{
"email":"[email protected]",
"firstName":"John",
"id":"111",
"lastName":"Smith",
"password":"111",
"phone":"555",
"wage":30.0
},
"222":{
"email":"[email protected]",
"firstName":"Jane",
"id":"222",
"lastName":"Doe",
"password":"222",
"phone":"678",
"wage":32.5
}
},
"-Lwsj8yE6HW2IUoTVJ0G":{
"111":{
"email":"[email protected]",
"firstName":"John",
"id":"111",
"lastName":"Smith",
"password":"111",
"phone":"555",
"wage":30.0
}
}
},
"shifts":{
"-Lwo52vuW9QqCmAfS90w":{
"date":"20191224",
"endTime":"12:00",
"key":"-Lwo52vuW9QqCmAfS90w",
"startTime":"10:00"
},
"-Lwsj8yE6HW2IUoTVJ0G":{
"date":"20191224",
"endTime":"14:00",
"key":"-Lwsj8yE6HW2IUoTVJ0G",
"startTime":"11:00"
}
},
"user-assign":{
"111":{
"-Lwo52vuW9QqCmAfS90w":{
"date":"20191224",
"endTime":"12:00",
"key":"-Lwo52vuW9QqCmAfS90w",
"startTime":"10:00"
},
"-Lwsj8yE6HW2IUoTVJ0G":{
"date":"20191224",
"endTime":"14:00",
"key":"-Lwsj8yE6HW2IUoTVJ0G",
"startTime":"11:00"
}
},
"222":{
"-Lwo52vuW9QqCmAfS90w":{
"date":"20191224",
"endTime":"12:00",
"key":"-Lwo52vuW9QqCmAfS90w",
"startTime":"10:00"
}
}
},
"users":{
"99999":{
"email":"",
"firstName":"Admin",
"id":"99999",
"lastName":"",
"password":"111",
"phone":"",
"wage":0
},
"111":{
"email":"[email protected]",
"firstName":"John",
"id":"111",
"lastName":"Smith",
"password":"111",
"phone":"555",
"wage":30.0
},
"222":{
"email":"[email protected]",
"firstName":"Jane",
"id":"222",
"lastName":"Doe",
"password":"222",
"phone":"678",
"wage":32.5
}
}
}
我能够插入,读取和删除User
和Shift
对象,但是在更新它们时,事情变得有些复杂。
例如,如果我想更新用户的工资,则必须遍历该用户分配的所有班次(在user-assign/$id
下),存储所有班次的键,然后为每个班次引用shift-assign/$shift-key
存储密钥并更新工资。这将需要嵌套的EventListener
,我正试图避免。
与显然地更新Shift
节点的相同问题。
是否有更好的方法来解决这个问题?
您实际上应该只引用user-assign
和shift-assign
节点中的ID,而不要引用整个对象。非规范化不需要您创建整个文档的重复副本。例如,简化您的结构将导致:
{
"shift-assign":{
"-Lwo52vuW9QqCmAfS90w": ["111", "222"],
"-Lwsj8yE6HW2IUoTVJ0G": ["111"]
},
"shifts":{
"-Lwo52vuW9QqCmAfS90w":{
"date":"20191224",
"endTime":"12:00",
"key":"-Lwo52vuW9QqCmAfS90w",
"startTime":"10:00"
},
"-Lwsj8yE6HW2IUoTVJ0G":{
"date":"20191224",
"endTime":"14:00",
"key":"-Lwsj8yE6HW2IUoTVJ0G",
"startTime":"11:00"
}
},
"user-assign":{
"111":["-Lwo52vuW9QqCmAfS90w", "-Lwsj8yE6HW2IUoTVJ0G"],
"222":["-Lwo52vuW9QqCmAfS90w"]
},
"users":{
"99999":{
"email":"",
"firstName":"Admin",
"id":"99999",
"lastName":"",
"password":"111",
"phone":"",
"wage":0
},
"111":{
"email":"[email protected]",
"firstName":"John",
"id":"111",
"lastName":"Smith",
"password":"111",
"phone":"555",
"wage":30.0
},
"222":{
"email":"[email protected]",
"firstName":"Jane",
"id":"222",
"lastName":"Doe",
"password":"222",
"phone":"678",
"wage":32.5
}
}
}
然后,您可以只执行客户端联接来检索其关联的对象。
这具有几个优点:
将地图用作路径(重制后)和值,然后使用updateChildren方法
例如,如果要更新用户的多个名称,则为>]
Map<String, Object> map = new HashMap<>(); //key for path and value in map for value in node map.put("/users/" + userId1 + "/name/", "ahmad"); map.put("/users/" + userId2 + "/name/", "mahmoud"); map.put("/users/" + userId3 + "/name/", "martin"); map.put("/users/" + userId4 + "/name/", "nameValue"); //and so on myRootRef.updateChildren(map);
依此类推,如果您有多个数据,则可以使用循环