couchbase - 无法部署Couchbase事件功能

标签 couchbase n1ql spring-data-couchbase

我在存储学生记录的存储桶中有一个文档“学生”,其中记录了id。

{
  "id":"101",
  "fname": "abc",
  "lname": "xyz",
  "rank": "1",
  "scholarShip": "",
  "grade": ""
}


我的工作是找到所有排名为1的学生,然后在各自的文档中更新“奖学金”和“成绩”。

我在Couchbase中创建了一个事件函数,如下所示

function OnUpdate(doc, meta) {
    log('docId', meta.id);
       try {
        var rankValue = SELECT rank FROM `student-records` USE KEYS ["id"];
        for (var rv of rankValue) {
            if (rv==1) {  
               UPDATE `student-records` USE KEYS ["id"] set scholarShip="100%", grade="A";
        }
     }
    } catch(e) { log(e); } 
}


部署此时,我得到一个错误:


部署失败:语法错误(7,16)-无法在以下位置执行DML查询
桶“学生记录”


创建函数时,我声明了:

源存储桶=>学生记录

元数据存储桶=>学生记录元数据

最佳答案

让我们逐步解决您的问题-直观地我知道答案(写到源存储桶(问题A)和不正确使用键(问题B))-但是我们可以通过逐步改进您的代码来突出显示两者练习并向您解释您的需求。首先,假设您在学生记录旁边将有其他文档,因此添加我添加了“类型”字段。在下面,我显示了一个可以放入您的“学生记录”中的示例记录(类型=学生,这是我添加的字段)。

{  "id":"101", "fname": "abc", "lname": "xyz", 
"rank": "1", "scholarShip": "", "grade": "", 
"type": "student" }


接下来,由于沙发床可以更好地将存储桶的数量限制为大约10个存储桶(对于Beta版本6.5,则为30个存储桶)。我们实际上并不希望为各个事件功能使用一大堆不同的“元数据”存储桶,因此我通常为所有事件功能创建一个称为“元”的公共存储桶。如果您考虑同样的话,通过添加类型字段,您可以在存储桶中存储许多不同类型的数据,因此为什么不将student-records重命名为通用的school存储桶。因此,存储区school可以容纳多种类型:类型=学生类型=老师,类型=教室,类型=时间表等。

因此,我创建了两个存储桶1)school和2 meta,然后通过UI的QUERY编辑器插入了一个测试记录。

INSERT INTO `school` ( KEY, VALUE ) VALUES
(
   "student101",
   {  "id":"101", "fname": "abc", "lname": "xyz", 
      "rank": "1", "scholarShip": "", "grade": "", "type": "student" }
)


为了帮助/允许我们查询特定类型,让我们在UI的QUERY编辑器中建立一个N1QL索引

CREATE INDEX adv_type ON `school`(`type`);


现在让我们在UI的QUERY编辑器中查看测试数据

SELECT * FROM `school` WHERE type = "student";


返回预期的JSON数据

[
  {
    "school": {
      "fname": "abc",
      "grade": "",
      "id": "101",
      "lname": "xyz",
      "rank": "1",
      "scholarShip": "",
      "type": "student"
    }
  }
]


在将N1QL放到Eventing中之前,始终将N1QL进行测试是一个好习惯,因此让我们在UI的QUERY编辑器中进行一次试运行。请查看KEY以及如何将其构造为“类型”和“ id”的串联,因此我们拥有一个现有的KEY-这与问题B有关,您在原始Eventing函数中使用了字符串“ id” 。

UPDATE `school` USE KEYS ["student101"] 
set scholarShip="100%", grade="A" WHERE type="student";


再来看一下结果

SELECT * FROM `school` WHERE type = "student";


返回预期的JSON数据

[
  {
    "school": {
      "fname": "abc",
      "grade": "A",
      "id": "101",
      "lname": "xyz",
      "rank": "1",
      "scholarShip": "100%",
      "type": "student"
    }
  }
]


现在,让数据恢复原样(我不显示结果)

UPDATE `school` USE KEYS ["student101"] 
set scholarShip="", grade="" WHERE type="student";


注意,由于我们使用的是键,因此我不需要在先前的UPDATE语句中使用WHERE type =“ student”子句,但是它着重说明了在同一个存储桶中有多个类型时如何进行区分。

好的,现在是时候创建Eventing函数了,但是在这一点上,我们必须了解一些有关Eventing的方面。


对于通过6.0.X发布的Couchbase版本,您无法写回
通过Eventing创建源存储桶。
对于6.5(测试版预览),您可以
通过别名的KV地图写回源存储桶(但不通过
N1QL)。


出现此限制的原因是,您可以创建循环依赖关系来触发无休止的递归Eventing操作,并且与从别名KV映射上的Eventing函数了解直接操作相比,很难在N1QL中检测到此类情况。

因此,继续前进,实现您的实际Eventing函数,您有两种选择,可以使您的实际Eventing函数对N1QL使用6.5查询,但可以通过KV向后戳位或创建目标存储桶。我假设在这种情况下,当我们定义函数时,我们要使用6.5-beta,我们需要a)“学校”的源存储桶,b)“元”的元数据存储桶,以及c)代表“学校”的存储桶别名将“学校”存储桶设置为“读写”,如下所示:

setup screen

请注意,在创建别名时不要使用'-'字符,因为它是非法的JavaScript变量名称,并且在您尝试部署Eventing函数时会抱怨。

而且这里的事件代码我们甚至不需要使用N1QL,我们使用公开的Javascript KV映射(我为存储桶“ school”使用了别名“ school”,该别名是一个通过其KEYS公开存储桶的Javascript映射。

function OnUpdate(doc, meta) {
    log('docId', meta.id);
    if (doc.type != "student") return;
    if (doc.rank == 1) {
        try {
            doc.grade = "A";
            doc.scholarShip = "100%";
            school[meta.id] = doc;
        } catch(e) { 
            log(e); 
        } 
    }
}


现在,如果部署该功能(适用于所有功能),您将看到Eventing自动更新您拥有的唯一记录,因为该记录的排名为1。

运行选择查询并亲自查看例如

SELECT * FROM `school` WHERE type = "student";


如果Eventing工作正常,您可以通过我们之前的UPDATE将数据放回去,但是由于Eventing会产生突变,Eventing会立即将其更改回已处理状态(请确保更新确实有效,但是由于rank = 1会重新进行处理,因为Eventing正在运行,并且部署,并获取您在QUERY UI中创建的变异):

UPDATE `school` USE KEYS ["student101"] 
set scholarShip="", grade="" WHERE type="student";


当然,每次运行事件时,都会将其写入日志(可通过UI的“事件”选项卡访问您的Function)信息,如下所示:

2019-12-12T15:30:18.153-07:00 [INFO] "docId" "student101"


如果您需要有关N1QL的帮助或实施6.5.5版之前的解决方案,请随时直接与我联系。

关于couchbase - 无法部署Couchbase事件功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59311323/

相关文章:

.net - NLog 的 Couchbase

database - CouchBase 索引嵌套元素

sql - Couchbase 查询按数组中的标签过滤

java - 嵌套引用对象持续为 null

java - spring-data-couchbase 为不存在的文档抛出 DocumentDoesNotExistException

spring - 使用@WebMvcTest 时如何排除使用 Spring 的 AutoConfiguration 添加的类?

http - 如何在nifi中使用invoke http来执行GET请求?

java - 为 Couchbase lite 2.x 和同步网关设置复制器时出现问题

ios - 沙发底座精简版 N1QL : how to query a array for a array of values

database - Couchbase,两个用户使用相同的用户名但不同的数据中心注册?