Firebase中的三方关系



在过去的几个月里,我学到了很多关于去规范化数据的知识,但我想知道在扁平化的体系结构世界中,以下内容是否可行。我知道如何在Firebase中处理双向关系,但三方关系呢。让我解释一下。。。

我的数据库中有5个项目,servicesprovidersserviceAtProviderreviewsusers。我希望能够将providers添加到services,反之亦然。

我还希望在service中有一个provider的特定页面,并且有链接到该特定服务提供商的评论。页面url可能如下所示(site.com/serviceId/providerId)。serviceId内的providerId的评级是唯一的——您不能分别对serviceIds或providerIds进行评级。

我不知道如何去建立这样一种复杂的关系。我将如何加入serviceAtProvider项目中的serviceIdproviderId

这就是我目前所掌握的:

"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.nameprovider1.nameservice1AtProvider1.ratingreviews.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" }
}
}

我首先会让数据结构更简单、更直接。如果没有详细的用例,很难确定适合您需求的正确数据结构。我将尽我所能在这里做一些一般性的假设。你必须根据需要进行调整。

{
"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);
});

请注意,这里没有什么是一成不变的。这就是我的做法。可能有几十种结构至少同样好或更好。

最新更新