过去几个月我一直在学习非规范化数据,但是我想知道在扁平化的架构世界中是否有以下几种可能。我知道如何处理Firebase中的双向关系,但是三方关系呢?让我解释一下......
我的数据库中有5个项目,services
,providers
,serviceAtProvider
,reviews
和users
。我希望能够将providers
添加到services
,反之亦然。
我还希望在provider
内有一个service
的特定页面,并且在该特定服务上有与该提供商相关联的评论。页面网址可能如下所示(site.com/serviceId/providerId
)。该评分对于providerId
内serviceId
的评分是唯一的 - 您无法单独评价serviceId
或providerId
。
我不确定如何创建如此复杂的关系。如何加入serviceId
项目中的providerId
和serviceAtProvider
?
这是我到目前为止所得到的:
"services": {
"service1": {
"name": "Hernia Repair",
"providers": {
"provider1": true,
"provider2": true
}
}
},
"providers": {
"provider1": { "name": "The Whittington Hospital" },
"provider2": { "name": "Homerton Hospital" }
},
"serviceAtProvider": {
"service1AtProvider1": { "rating": 4 },
"service1AtProvider2": { "rating": 3 }
},
"reviews": {
"service1AtProvider1": {
"review1": {
"body": "A review from user 1",
"user": "user1"
}
},
"service1AtProvider2": {
"review1": {
"body": "A review from user 2",
"user": "user2"
}
}
},
"users": {
"user1": { "name": "Ben Thomas" },
"user2": { "name": "Beatrix Potter" }
}
我不知道如何创建serviceAtProvider
加入,或者我将如何访问service1.name
,provider1.name
,service1AtProvider1.rating
,reviews.service1AtProvider1
在一页上。任何人都可以解释如何做到这一点吗?
此外,我应该遵循哪些最佳做法?
感谢任何帮助。提前谢谢!
更新
{
"availableServices": {
"service1": { "name": "Hernia Repair" },
"service2": { "name": "Chemotherapy" }
},
"services": {
"provider": {
"name": "The Whittington Hospital",
"service": {
"service1": {
"rating": 4,
"reviewId1": true
},
"service2": {
"rating": 3,
"reviewId2": true
},
}
}
},
"reviews": {
"reviewId1": {
"review1": {
"rating": 4,
"body": "A review from user 1",
"user": "user1"
}
}
},
"users": {
"user1": { "name": "Raphael Essoo-Snowdon" },
"user2": { "name": "Sharlyne Slassi" }
}
}
答案 0 :(得分:2)
我首先要使数据结构更简单,更直接。没有详细的用例,很难根据需要确定正确的数据结构。我会尽力在这里做一些通用的假设。你必须根据需要进行调整。
{
"service": {
"service1": { "name": "Foo Service" },
...
},
"provider": {
"provider1": { name: "Foo Place" },
...
},
"ratings": {
"service1": { // service id
"provider1": { // provider id
"average_rating": 4
},
...
},
...
},
"reviews": {
"service1": { // service id
"provider1": { // provider id
"user": "user1",
"rating": 4
},
...
},
...
},
"user": {
"user1": { "name": "Foo Bar" },
...
}
}
现在,要查找提供给定服务的提供商并获取他们的评论,我会执行以下操作:
var ref = new Firebase(...);
ref.child('ratings/service1').on('child_added', function(reviewSnap) {
console.log(
'Provider ' + reviewSnap.key(),
'Average rating ' + reviewSnap.val().average_rating
);
});
加入服务和提供者的名称可以通过多种方式完成。这是一种手动技术:
var ref = new Firebase(...);
ref.child('ratings/service1').on('child_added', accumulateReview);
function accumulateReview(reviewSnap) {
var reviewData = reviewSnap.val();
var reviewid = reviewSnap.key();
fetchService(reviewSnap.parent().key(), function(serviceSnap) {
loadRec('provider', reviewSnap.key(), function(providerSnap) {
console.log('Provider: ', providerSnap.key(), providerSnap.val().name);
console.log('Service: ', serviceSnap.key(), serviceSnap.val().name);
console.log('Average rating: ', reviewData.average_rating);
});
});
}
var serviceCache = {};
function fetchService(serviceid, done) {
// demonstrates creating a local cache for things that will be
// looked up frequently
if( !serviceCache.hasOwnProperty(serviceid) ) {
cacheService(serviceid, done);
}
else {
done(serviceCache[serviceid]);
}
}
function cacheService(serviceid, done) {
loadRec('service', function(ss) {
serviceCache[serviceid] = ss;
fetchService(serviceid, done);
});
}
function loadRec(type, key, done) {
ref.child(type).child(key).once('value', done);
}
我还可以使用Firebase.util NormalizedCollection自动完成部分过程:
var ref = new Firebase(...);
var nc = Firebase.util.NormalizedCollection(
[ref.child('reviews/service1'), 'review'],
ref.child('provider'),
ref.child('user')
)
.select('review.rating', {key: 'provider.name', alias: 'providerName'}, {key: 'user.name', alias: 'userName'})
.ref();
nc.on('child_added', function(snap) {
var data = snap.val();
console.log('Provider', data.providerName);
console.log('User', data.userName);
console.log('Rating', data.rating);
});
请注意,这里没有任何内容。这就是我接近它的方式。可能有数十种结构至少同样好或更好。