json - Firebase 中的三向关系

标签 json firebase firebase-realtime-database database nosql

在过去的几个月里,我学习了很多关于非规范化数据的知识,但我想知道在扁平化架构世界中是否可能出现以下情况。我知道如何在 Firebase 中处理双向关系,但如何处理三向关系呢?让我解释一下...

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

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

我不确定如何着手建立如此复杂的关系。我如何将 serviceIdproviderId 加入那个 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.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);
});

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

关于json - Firebase 中的三向关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29784298/

相关文章:

java - jackson JSON : Serialize Array of Objects as their parent type

javascript - Bootstrap 的 AngularJS 分页不显示下一个/上一个按钮

C 中节俭的编码示例,使用文件

javascript - 已发布的 React 应用程序中函数的可变性

javascript - 无法为 Firebase 部署 Cloud Functions

javascript - 解析完整的 json 并搜索与值匹配的键

ios - "Copy this file to your authentication server"- Firebase 自定义身份验证

java - DatabaseException - 无法将 java.lang.String 类型的对象转换为 com.appmaster.akash.messageplus.Results 类型

node.js - 为什么 Cloud Functions for Firebase 需要 25 秒?

firebase - 在 vuex 操作中访问 this.$fireStore (Nuxt.js)