Optimization Couchdb视图和许多(数千)文档类型
我正在学习CouchDB,我正在想象一个最坏的情况: 对于每种文档类型,我需要3个视图,该应用程序可以生成10000种文档类型 对于文档类型,我指的是文档的结构 插入新文档后,couchdb进行3*10K调用以查看搜索正确文档类型的函数 这是真的吗? 除了为每种文档类型创建一个数据库之外,还有什么聪明的解决方案吗 文档示例假设没有文档具有相同的结构,在此示例中,数据位于不同的键下:Optimization Couchdb视图和许多(数千)文档类型,optimization,view,couchdb,organization,Optimization,View,Couchdb,Organization,我正在学习CouchDB,我正在想象一个最坏的情况: 对于每种文档类型,我需要3个视图,该应用程序可以生成10000种文档类型 对于文档类型,我指的是文档的结构 插入新文档后,couchdb进行3*10K调用以查看搜索正确文档类型的函数 这是真的吗? 除了为每种文档类型创建一个数据库之外,还有什么聪明的解决方案吗 文档示例假设没有文档具有相同的结构,在此示例中,数据位于不同的键下: [ { "_id":"1251888780.0", "_rev":"1-58
[
{
"_id":"1251888780.0",
"_rev":"1-582726400f3c9437259adef7888cbac0"
"type":'sensorX',
"value":{"ValueA":"123"}
},
{
"_id":"1251888780.0",
"_rev":"1-37259adef7888cbac06400f3c9458272"
"type":'sensorY',
"value":{"valueB":"456"}
},
{
"_id":"1251888780.0",
"_rev":"1-6400f3c945827237259adef7888cbac0"
"type":'sensorZ',
"value":{"valueC":"789"}
},
]
视图示例在本示例中,每个文档类型仅一个视图
"views":
{
"sensorX": {
"map": "function(doc) { if (doc.type == 'sensorX') emit(null, doc.valueA) }"
},
"sensorY": {
"map": "function(doc) { if (doc.type == 'sensorY') emit(null, doc.valueB) }"
},
"sensorZ": {
"map": "function(doc) { if (doc.type == 'sensorZ') emit(null, doc.valueC) }"
},
}
CouchDB中map函数的结果在您第一次为每个新文档请求视图时被缓存。让我用一个简单的例子来解释
您可以向CouchDB插入100个文档
您请求查看。现在,100个文档对其运行map函数,并缓存结果
您再次请求查看。从索引视图数据读取数据,无需重新映射文档
再插入50个文档
您请求查看。50个新文档被映射并与旧的100个文档合并到索引中
您再次请求查看。从索引视图数据读取数据,无需重新映射文档。
我希望这是有道理的。如果您担心当用户请求视图并且添加了大量新文档时会产生很大的负载,那么可以考虑让导入过程调用视图来重新映射新文档,并让用户请求视图include stale=ok
对于CouchDB的信息来说,是一个非常好的资源。CouchDB中map函数的结果在您第一次为每个新文档请求视图时被缓存。让我用一个简单的例子来解释
您可以向CouchDB插入100个文档
您请求查看。现在,100个文档对其运行map函数,并缓存结果
您再次请求查看。从索引视图数据读取数据,无需重新映射文档
再插入50个文档
您请求查看。50个新文档被映射并与旧的100个文档合并到索引中
您再次请求查看。从索引视图数据读取数据,无需重新映射文档。
我希望这是有道理的。如果您担心当用户请求视图并且添加了大量新文档时会产生很大的负载,那么可以考虑让导入过程调用视图来重新映射新文档,并让用户请求视图include stale=ok
这是一个关于CouchDB的非常好的信息来源。詹姆斯有一个很好的答案 看起来您在问这样一个问题:X类型文档的值是多少 我认为你可以用一种观点来做到这一点:
function(doc) {
// _view/sensor_value
var val_names = { "sensorX": "valueA"
, "sensorY": "valueB"
, "sensorZ": "valueC"
};
var value_name = val_names[doc.type];
if(value_name) {
// e.g. "sensorX" -> "123"
// or "sensorZ" -> "789"
emit(doc.type, doc.value[value_name]);
}
}
现在,要获取sensor的所有值,您可以使用参数?key=sensorX查询/db/_design/app/_view/sensor_value。CouchDB将显示sensorX的所有值,这些值来自文档的value.valueA字段。对于感官,它来自value.valueB等
未来证明
如果将来您可能会有新的文档类型,那么使用更通用的文档类型可能会更好:
function(doc) {
if(doc.type && doc.value) {
emit(doc.type, doc.value);
}
}
这非常简单,任何文档都可以使用类型和值字段。接下来,要从视图中获取valueA、valueB等,只需在客户端执行此操作
如果无法使用客户端,请使用_list函数
function(head, req) {
// _list/sensor_val
//
start({'headers':{'Content-Type':'application/json'}});
// Updating this will *not* cause the map/reduce view to re-build.
var val_names = { "sensorX": "valueA"
, "sensorY": "valueB"
, "sensorZ": "valueC"
};
var row;
var doc_type, val_name, doc_val;
while(row = getRow()) {
doc_type = row.key;
val_name = val_names[doc_type];
doc_val = row.value[val_name];
send("Doc " + row.id + " is type " + doc_type + " and value " + doc_val);
}
}
显然,使用send发送您喜欢的客户端格式,如JSON。James有一个很好的答案 看起来您在问这样一个问题:X类型文档的值是多少 我认为你可以用一种观点来做到这一点:
function(doc) {
// _view/sensor_value
var val_names = { "sensorX": "valueA"
, "sensorY": "valueB"
, "sensorZ": "valueC"
};
var value_name = val_names[doc.type];
if(value_name) {
// e.g. "sensorX" -> "123"
// or "sensorZ" -> "789"
emit(doc.type, doc.value[value_name]);
}
}
现在,要获取sensor的所有值,您可以使用参数?key=sensorX查询/db/_design/app/_view/sensor_value。CouchDB将显示sensorX的所有值,这些值来自文档的value.valueA字段。对于感官,它来自value.valueB等
未来证明
如果将来您可能会有新的文档类型,那么使用更通用的文档类型可能会更好:
function(doc) {
if(doc.type && doc.value) {
emit(doc.type, doc.value);
}
}
这非常简单,任何文档都可以使用类型和值字段。接下来,要从视图中获取valueA、valueB等,只需在客户端执行此操作
如果无法使用客户端,请使用_list函数
function(head, req) {
// _list/sensor_val
//
start({'headers':{'Content-Type':'application/json'}});
// Updating this will *not* cause the map/reduce view to re-build.
var val_names = { "sensorX": "valueA"
, "sensorY": "valueB"
, "sensorZ": "valueC"
};
var row;
var doc_type, val_name, doc_val;
while(row = getRow()) {
doc_type = row.key;
val_name = val_names[doc_type];
doc_val = row.value[val_name];
send("Doc " + row.id + " is type " + doc_type + " and value " + doc_val);
}
}
显然,可以使用send发送您喜欢的客户端格式,如JSON。您能提供一个示例,说明您所说的文档类型是什么意思吗?我认为您的文档示例不包含文档,而是视图的结果。你能寄一些样品文件吗?你可以通过找到它们。你能提供一个你所说的文档类型的示例吗?我认为你的文档示例不包含文档,而是一个视图的结果。你能寄一些样品文件吗?你可以通过找到它们。是的,我现在看到CouchDB缓存查看结果,我的
怀疑的是,我的设计文档中是否有数千个视图函数。我认为您需要重新考虑如何使用CouchDB。拥有数千个视图功能几乎肯定是一个糟糕的计划。我建议您修改视图函数,使其发出一个[doc.type,doc.value]键。您需要确保view函数包含使用要发出的值进行计算的逻辑。问题是我不知道使用每个文档类型的逻辑,它是用户定义的,最糟糕的情况是每个用户都有自己的逻辑。这就是为什么我的第一个想法是使用像适配器这样的视图在结构已知的文档中转换结构未知的文档。对于每种数据类型使用一个db,您认为如何?CouchDB可以处理数千个数据库吗?是的,CouchDB可以在一台服务器上处理数百万个数据库,但我只需要在一个数据库中处理所有不同的数据类型。它使您不必在创建它们时知道它们是什么类型。我怀疑如果您有数千个数据库,您将开始遇到fs问题。我建议大家从其他方面来解决这个问题,比如在数据进入CouchDb之前对其进行规范化,或者完全重新考虑数据模型。是的,我现在知道CouchDb缓存了视图结果,我的疑问是,我的设计文档中是否有数千个视图函数。我认为你需要重新考虑你打算如何使用CouchDb。拥有数千个视图功能几乎肯定是一个糟糕的计划。我建议您修改视图函数,使其发出一个[doc.type,doc.value]键。您需要确保view函数包含使用要发出的值进行计算的逻辑。问题是我不知道使用每个文档类型的逻辑,它是用户定义的,最糟糕的情况是每个用户都有自己的逻辑。这就是为什么我的第一个想法是使用像适配器这样的视图在结构已知的文档中转换结构未知的文档。对于每种数据类型使用一个db,您认为如何?CouchDB可以处理数千个数据库吗?是的,CouchDB可以在一台服务器上处理数百万个数据库,但我只需要在一个数据库中处理所有不同的数据类型。它使您不必在创建它们时知道它们是什么类型。我怀疑如果您有数千个数据库,您将开始遇到fs问题。我建议你用其他方法来解决这个问题,也许在进入CouCHDB之前对数据进行归一化或重新考虑数据模型的完整性。这个解决方案的缺点是何时应该添加一个新的DOC类型:视图应该被重新构建来解析所有文档。更新答案以考虑未知的未来文档类型。类型:应重新构建视图解析所有文档。更新答案以考虑未知的未来文档类型