Now, this is not the end. It is not even the beginning of the end. But it is, perhaps, the end of the beginning. — Winston Churchill
Updating data is usually not the end, but usually a progress of a workflow. Shipping follows ordering; inventory update follows shipping; adjusting credit follows returning; The next step in the process is required to act to keep the workflow going. The workflows can be simple with few steps or complex with hundreds of steps. Business Process Management (BPM) is an industry by itself.
Couchbase 5.5 introduced Evening service. Developers can write a Javascript function to execute upon a change to the data. We refer inserts, Updates, Merges, and Deletions together as mutations. Multiple specific use cases have been documented for developing these 이벤트 함수.
JSON 카우치베이스의 데이터 모델은 자바스크립트. N1QL is SQL for JSON. The eventing functions are written in Javascript and has integrated N1QL. Using the Eventing functions, writing procedural business logic with instant access to data easy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// Simple counting function // After every update to travel sample, keep track of the total number of documents of each type. 함수 온업데이트(doc, 메타) { 시도 { // Issue SELECT statement to get the counts. var ginfo = 선택 유형, COUNT(유형) typecount FROM `여행-샘플` 어디 `유형` IS NOT 누락 그룹 BY 유형; // loop through the resultset 에 대한 (var val 의 ginfo) { var ckey = "trcount" + val.유형; // Create the document key-string. var vtype = val.유형; var vtc = val.typecount; // get the type, count // do the update. 업데이트 T1 사용 키[$ckey] SET 유형 = $vtype, typecount =$vtc; } } catch(e) { 로그(e); } } |
Here’s the lifecycle of the functions from a developer perspective. For every mutation, you can define any number of these functions to be executed. It’s the developer responsibility to size the execution times of the functions, depending on the number of mutations.
Here’s the lifecycle of the Eventing functions:
For every insert, update or delete (direct or expiry), you can execute one or more javascript functions. These functions can read the new data and type of action and then execute the subsequent action. This functionality is well described in Couchbase blogs, and articles.
Statement Type | Eventing Function Invoked |
선택 | 없음 |
삽입 | OnUpdate(). The function is invoked once per document inserted. Simple insert inserts a single document. Inserts can have multiple documents using multiple documents in the VALUES clause or can insert multiple documents via INSERT INTO…SELECT statement. |
업데이트 | OnUpdate() is invoked once per document updated, except when multiple updates on the same document is deduped into a single update. Update statement can update multiple documents. |
UPSERT | OnUpdate(). The behavior is similar to INSERT. |
삭제 | OnDelete(). Invoked once per documented deleted. |
MERGE | OnUpdate() and/or OnDelete() depending on the insert, update, and delete actions. |
CREATE INDEX, DROP INDEX, EXPLAIN, PREPARE, GRANT, REVOKE | No eventing function is invoked. |
실행 | Depends on the type of the statement executed. |
These functions can also execute N1QL statements. Rest of the article looks at all aspects of N1QL executed in Eventing Functions.
N1QL Statements in Eventing functions.
성명서 | Use cases for N1QL statements in Eventing Functions |
인덱스 생성 | Since the schema is flexible, you could potentially inspect the data often/periodically to detect new fields and then create indexes on it. |
삭제 | Cascade deletes. |
DROP INDEX | A corollary to the CREATE INDEX use case. |
INFER | Periodic introspection of the bucket for the structure. Then take action (validate, create index, update the data model) if necessary. |
삽입 | Maintaining referential data (eventually).
Updating other documents with references to this data. E.g Data from a new zip, state, etc. Data copy (fully or partially) to secondary/tertiary documents. Similar to post-trigger action. |
MERGE | Keep the secondary data in sync. |
선택 | Fetch any data, run any reports periodically, etc.
Check for various things like data quality, data validity, When you do know the target document key, use the built-in direct document references. See examples at: https://docs.couchbase.com/server/5.5/eventing/eventing-examples.html |
UPSERT | Keeping secondary/tertiary data in sync.
Similar to post-trigger action. |
업데이트 | Keeping secondary/tertiary data in sync.
Similar to post-trigger action. |
Examples: Let’s try some eventing functions with N1QL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
선택 메타().id, * 에서 실행 S1; [ { "S1": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" }, { "S1": { "name": "John Smith", "zip": "94040" }, "id": "John::94040" } ] 선택 메타().id, * 에서 S2; [ { "S2": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" }, { "S2": { "name": "John Smith", "zip": "94040" }, "id": "John::94040" } ] 선택 메타().id, * 에서 T1; <아니요 데이터> |
- Simple N1QL in Functions for logging and cascade delete.
Save away every deleted document in a separate bucket.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
함수 온업데이트(doc, 메타) { } 함수 OnDelete(메타) { 시도 { var myid = 메타.id; //Insert into the bucket of 삽입 INTO T1 가치(UUID(), {"type" : "삭제됨", "docid":$myid}); //Cascade delete 삭제 FROM S2 사용 키 [$myid]; } catch(e) { 로그(e); } } 이후 만들기 의 함수 위, 의 애플리케이션 실행 의 다음: 삭제 FROM S1 어디 zip = "94040"; // One document was deleted. 선택 메타().id, * 에서 S1; // one document just got deleted. There should be only one document remaining. [ { "S1": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" } ] 선택 메타().id, * 에서 T1; // We should see a log of the deleted [ { "T1": { "docid": "John::94040", "type": "삭제됨" }, "id": "2dc9b33d-3cd4-422e-af9c-b0c664c4660f" } ] 선택 메타().id, * FROM S2; // We should only see one document due to the effect of cascade delete from the the function [ { "S2": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" } ] |
- OnUpdate() function to keep the aggregate information ready periodically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
함수 온업데이트(doc, 메타) { 시도 { var stattime = 선택 lastupdate FROM T1 사용 키 ["trstattime"]; 에 대한 (var t 의 stattime) { var lt = t.lastupdate; var d = new 날짜(); var n = d.getTime(); // Every 10 minutes or more 만약 ((n - lt) > (1000 * 60 * 10)) { 업데이트 T1 사용 키["trstattime"] SET lastupdate = NOW_MILLIS() ; var ginfo = 선택 유형, 카운트(유형) typecount FROM `여행-샘플` 어디 `유형` IS NOT 누락 그룹 BY 유형; 에 대한 (var val 의 ginfo) { var ckey = "trcount::" + val.유형; var vtype = val.유형; var vtc = val.typecount; 업데이트 T1 사용 키[$ckey] SET 유형 = $vtype, typecount = $vtc; } } } } catch(e) { 로그(e); } } |
참조:
- Couchbase documentation: https://docs.couchbase.com/server/5.5/eventing/eventing-overview.html
- Couchbase blogs on eventing: https://www.couchbase.com/blog/tag/eventing/