C# 为chouchbase中的特定数据检索创建特定视图

C# 为chouchbase中的特定数据检索创建特定视图,c#,linq,couchbase,nosql,C#,Linq,Couchbase,Nosql,我的一个队友和我讨论了在couchbase中创建视图以检索数据的问题 所以我的建议是为特定的数据检索创建视图,这样会更快、更直接。例如,我们有两个不同的管理员: 特定组的管理员 超级管理员 管理员从他们的特定组中检索数据,超级管理员从所有组中获取数据 限制组管理员获取属于他们的数据,而不是获取所有数据,然后在后端处理这些数据并比较哪些数据属于一个组,这是有意义的 例如: 创建接受组id并查询其所有数据的couchbase视图 另一方面,她只在有复杂的东西(如计算)时创建视图,创建更多视图可能

我的一个队友和我讨论了在couchbase中创建视图以检索数据的问题

所以我的建议是为特定的数据检索创建视图,这样会更快、更直接。例如,我们有两个不同的管理员:

  • 特定组的管理员
  • 超级管理员
管理员从他们的特定组中检索数据,超级管理员从所有组中获取数据

限制组管理员获取属于他们的数据,而不是获取所有数据,然后在后端处理这些数据并比较哪些数据属于一个组,这是有意义的

例如: 创建接受组id并查询其所有数据的couchbase视图

另一方面,她只在有复杂的东西(如计算)时创建视图,创建更多视图可能很难维护

因为目前我们只使用一个视图来获取所有数据,一旦获得了这些数据,我们就通过使用LINQ获取后端特定组的特定数据来处理它们

文档结构:

{
   "fooReference": "",
   "groupId": 8,
   "fooName": "projectTest",
   "externalId": "PR572",
   "fooDescription": "OG QGpCst vXAuu",
   "property5": {
       "property1": "124",
       "code": "US",
       "value": 267206,
       "start": "2014-10-01T00:00:00Z",
       "end": "2017-09-30T00:00:00Z"
   },
   "property6": [
       "string1",
       "string2",
       "string14"
   ],
   "property7": [
   ],
   "property8": [
   ],
   "dateAdded": "2016-02-11T07:22:15.2483042Z",
   "ownerId": 72,
   "dateUpdated": "2016-02-11T07:22:15.2483042Z",
   "property9": [
       {
           "id": 72,
           "type": 0
       }
   ],
   "property10": false,
   "id": "345",
   "deleted": false,
   "type": "Foo",
   "subtype": "Foo"
}
function (doc, meta) {
  if (doc.type == "Foo" && !doc.deleted) {
    emit(meta.id, null); 
  }
}
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.GroupId == group.Id).ToList();
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.externalId == foo.externalId).ToList();
获取所有查询:

{
   "fooReference": "",
   "groupId": 8,
   "fooName": "projectTest",
   "externalId": "PR572",
   "fooDescription": "OG QGpCst vXAuu",
   "property5": {
       "property1": "124",
       "code": "US",
       "value": 267206,
       "start": "2014-10-01T00:00:00Z",
       "end": "2017-09-30T00:00:00Z"
   },
   "property6": [
       "string1",
       "string2",
       "string14"
   ],
   "property7": [
   ],
   "property8": [
   ],
   "dateAdded": "2016-02-11T07:22:15.2483042Z",
   "ownerId": 72,
   "dateUpdated": "2016-02-11T07:22:15.2483042Z",
   "property9": [
       {
           "id": 72,
           "type": 0
       }
   ],
   "property10": false,
   "id": "345",
   "deleted": false,
   "type": "Foo",
   "subtype": "Foo"
}
function (doc, meta) {
  if (doc.type == "Foo" && !doc.deleted) {
    emit(meta.id, null); 
  }
}
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.GroupId == group.Id).ToList();
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.externalId == foo.externalId).ToList();
这是我想建议的示例查询: 如果我想通过groupId获取它,只需在
emit

function(doc, meta) {
     if (doc.type == "Foo" && !doc.deleted) {
         emit(doc.groupId, doc);
     }
 }
function(doc, meta) {
         if (doc.type == "Foo" && !doc.deleted) {
             emit(doc.externalId, doc);
         }
     }
如果我想获得
externalId
,我只需要将
externalId
传递给
emit

function(doc, meta) {
     if (doc.type == "Foo" && !doc.deleted) {
         emit(doc.groupId, doc);
     }
 }
function(doc, meta) {
         if (doc.type == "Foo" && !doc.deleted) {
             emit(doc.externalId, doc);
         }
     }
通过这种方式,我们可以使用不同的查询来获取文档,而不必通过其
id
获取所有文档,并在后端使用LINQ处理它们

在后端处理它们的示例:

获取群组ID:

{
   "fooReference": "",
   "groupId": 8,
   "fooName": "projectTest",
   "externalId": "PR572",
   "fooDescription": "OG QGpCst vXAuu",
   "property5": {
       "property1": "124",
       "code": "US",
       "value": 267206,
       "start": "2014-10-01T00:00:00Z",
       "end": "2017-09-30T00:00:00Z"
   },
   "property6": [
       "string1",
       "string2",
       "string14"
   ],
   "property7": [
   ],
   "property8": [
   ],
   "dateAdded": "2016-02-11T07:22:15.2483042Z",
   "ownerId": 72,
   "dateUpdated": "2016-02-11T07:22:15.2483042Z",
   "property9": [
       {
           "id": 72,
           "type": 0
       }
   ],
   "property10": false,
   "id": "345",
   "deleted": false,
   "type": "Foo",
   "subtype": "Foo"
}
function (doc, meta) {
  if (doc.type == "Foo" && !doc.deleted) {
    emit(meta.id, null); 
  }
}
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.GroupId == group.Id).ToList();
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.externalId == foo.externalId).ToList();
获取外部ID:

{
   "fooReference": "",
   "groupId": 8,
   "fooName": "projectTest",
   "externalId": "PR572",
   "fooDescription": "OG QGpCst vXAuu",
   "property5": {
       "property1": "124",
       "code": "US",
       "value": 267206,
       "start": "2014-10-01T00:00:00Z",
       "end": "2017-09-30T00:00:00Z"
   },
   "property6": [
       "string1",
       "string2",
       "string14"
   ],
   "property7": [
   ],
   "property8": [
   ],
   "dateAdded": "2016-02-11T07:22:15.2483042Z",
   "ownerId": 72,
   "dateUpdated": "2016-02-11T07:22:15.2483042Z",
   "property9": [
       {
           "id": 72,
           "type": 0
       }
   ],
   "property10": false,
   "id": "345",
   "deleted": false,
   "type": "Foo",
   "subtype": "Foo"
}
function (doc, meta) {
  if (doc.type == "Foo" && !doc.deleted) {
    emit(meta.id, null); 
  }
}
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.GroupId == group.Id).ToList();
var foos = _fooRepository.GetAll();
foos = foos.Where(s => s.externalId == foo.externalId).ToList();
注意:性能对我们来说有些重要,特别是在呈现为用户检索数据的页面时


因此,我的问题是,对于这种情况,什么是最好的方法?

我还没有在实时系统上测试过您的方案,但是使用每个查询类型的视图看起来就像是针对您的需求的教科书式解决方案。如果需要查询通过不同的条件访问数据,请为每组条件定义一个视图

性能注意事项:

空间:您的每个视图都将为每个选定文档生成一个索引,其中包含发出的值和文档id。与您的总体数据量相比,这应该不会有任何问题。我能想象的唯一例外是硬件资源极其有限,例如,如果你的应用程序运行在一辆车的嵌入式硬件上,每一分钱都很重要

运行时:数据库上的操作总数取决于更改索引的插入和更新次数加上对数据的查询次数以及每个查询检索到的记录数。现在,如果相关插入/更新操作的计数超过查询的计数,则索引可能会增加操作的总数。然而,在大多数数据库应用程序中,查询要比修改操作多得多,因此使索引保持最新的每个操作都会因选择所需数据的工作量减少而得到更多的补偿。如果仍有疑问,您可以粗略估计与视图相关的插入、更新和查询操作的数量

从另一个角度来看,如果您需要根据某些标准选择数据,那么有两种方法可以实现这一点:在数据库中、使用视图或在应用程序中。在应用程序中执行此操作会带来两个性能问题:必须将更多数据从数据库传输到应用程序,并且应用程序需要包含一个选择算法,该算法很可能不会比数据库提供的算法更快


总而言之,除非插入/更新操作大大超过查询,否则为访问数据的不同方式定义视图才是正确的选择。

我还没有在实时系统上测试过您的方案,但为每种查询类型使用视图看起来像是满足您需求的教科书解决方案。如果需要查询通过不同的条件访问数据,请为每组条件定义一个视图

性能注意事项:

空间:您的每个视图都将为每个选定文档生成一个索引,其中包含发出的值和文档id。与您的总体数据量相比,这应该不会有任何问题。我能想象的唯一例外是硬件资源极其有限,例如,如果你的应用程序运行在一辆车的嵌入式硬件上,每一分钱都很重要

运行时:数据库上的操作总数取决于更改索引的插入和更新次数加上对数据的查询次数以及每个查询检索到的记录数。现在,如果相关插入/更新操作的计数超过查询的计数,则索引可能会增加操作的总数。然而,在大多数数据库应用程序中,查询要比修改操作多得多,因此使索引保持最新的每个操作都会因选择所需数据的工作量减少而得到更多的补偿。如果仍有疑问,您可以粗略估计与视图相关的插入、更新和查询操作的数量

从另一个角度来看,如果您需要根据某些标准选择数据,那么有两种方法可以实现这一点:在数据库中、使用视图或在应用程序中。在应用程序中这样做会带来两个性能问题:必须将更多的数据从数据库传输到应用程序,并且应用程序需要包括一个选择算法,该算法很可能不会比t快