SlideShare a Scribd company logo
1 
Couchbase MeetUP Tokyo - #11
自己紹介 
2 
•木次 恭一 
•Twitter: @kyoichi_kitsugi  
•ウイングソリューションズ(株) 
•仕事ではJavaがメイン 
•最近では Sencha Touch, ElasticSearchなど
Couchbase Mobileとの出会い 
3 
MongoDB 
CouchDB 
TouchDB 
Couchbase 
Server 
Sync 
Gateway 
Couchbase 
Lite 
CouchDB 
NoSQL 
に興味 
JSON 
大好き 
モバイル 
大好き
Couchbase Mobile Hackathon 
4 
ハッカソン開催 
•2014年9月7日開催 
•向上心溢れる暇な人が集結 
•Couchbase Liteを利用したアプリを作成 
•優勝したら一人だけサンフランシスコに行ける
Couchbase Mobile Hackathon 
5 
ROUND 1 
FIGHT
Couchbase Mobile Hackathon 
6 
TIME OVER 
5時間じゃ厳しいっす!!
Couchbase Mobile Hackathon 
7 
ヒソ( ´д)ヒソ(´д`)ヒソ(д` )ヒソ 
審査中 
ネェ、キイタ?( ´д)オクサン(д` )アラヤダワァ
Couchbase Mobile Hackathon 
8 
優勝
Couchbase Mobile Hackathon 
9 
勝因をしいてあげるなら 
•チームの人数が多かった 
•プレゼン資料が良かった 
•画面数が一番多かった
おもいでノート 
10 
行ったことがある場所A B 
Tom Jerry 
行ったことがない場所C 
行った事がある場所は 
自宅で閲覧・更新が可能 
その場所に行かないと 
何も出来ない
おもいでノート 
11 
デモ 
https://github.com/kitsugi/omoidebase
おもいでノート 
12 
行ったことがない場所
Couchbase Connect 
13 
•2014年10月6日~7日開催 
•サンフランシスコ 
•全米No1と僕が思ったNoSQLカンファレンス 
•スタバのコーヒーが飲み放題
Couchbase Connectの様子 
14
Couchbase Connectの様子 
15
Couchbase Connectの様子 
16
Couchbase Connectの様子 
17
Couchbase Connectの様子 
18
Couchbase Connectの様子 
19
おもいでノート 
20 
ドキュメント
Document種別 
21 
場所 
place 
コメント 
comment 
プロフィール 
コメント コメント 
tom 
comment 
comment 
場所 
place 
コメント 
comment 
コメント 
comment 
プロフィール 
jerry
場所 
{ 
"type" : "place", 
"code" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", 
"name" : "Westin San Francisco", 
"remark": "Couchbase Connect 2014 on Oct 6, 2014 in San Francisco", 
"location": { 
"latitude": 37.7876643, 
"longitude": -122.4090627 
}, 
"image" : "画像 (base64文字列)" 
}
コメント 
{ 
"type" : "comment", 
"place" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", 
"created_at" : "2014-11-17T13:56:52+09:00", 
"contents" : "内容", 
"image": "画像 (base64文字列)" 
}
プロフィール 
{ 
"type" : "profile", 
"name" : "tom", 
"places" : [ 
"ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", 
"89B038CD-84A9-442c-95D1-0E22CAF8EB9E" 
] 
}
おもいでノート 
25 
構築
構成図 
Couchbase Server 
Sync Gateway 
おもいでノート 
(Couchbase Lite) 
cURL等 
:8091 
Backet 
omoidebase 
:4985 
:4984 User, Roleの作成・削除 
マスタ投入 
おもいでノート 
(Couchbase Lite) 
26 
コメント作成コメント作成
構築1:バケット作成 
Couchbase Server 
:8091 
Backet 
omoidebase 
Admin Console等
構築2:Sync Gateway起動 
Backet 
omoidebase 
Couchbase Server 
:8091 
Sync Gateway 
Terminal等 
./sync_gateway config.json 
{ 
"interface": ":4984", 
"adminInterface": ":4985", 
"log": [ 
"REST" 
], 
"databases": { 
"omoidebase": { 
"server": "http://localhost:8091", 
"bucket": "omoidebase", 
"sync": ` function(doc, oldDoc) { 
if (doc.type === "profile") { 
if (doc.places) { 
for (var i = 0; i < doc.places.length; i++) { 
access(doc.name, doc.places[i]); 
} 
} 
access(doc.name, doc.name); 
channel(doc.name); 
} else if (doc.type === "comment") { 
channel(doc.place); 
} else if (doc.type === "place") { 
channel(doc._id); 
} 
}` 
} 
} 
} 
※データーベースは複数定義可能 
:4984 
:4985 
Sync 
Function
構築3:ユーザー作成 
Backet 
omoidebase 
Couchbase Server 
:8091 
Sync Gateway 
:4985 
cURL等 
tom 
password 
curl -XPOST -H "Content-Type: application/json" http://localhost:4985/omoidebase/ 
_user/ -d @user1.json 
{ 
"name": "tom", 
"password": "password" 
}
構築4:マスタ系データインポート 
Backet 
omoidebase 
Couchbase Server 
:8091 
Sync Gateway 
:4985 
cURL等 
場所プロフィール 
curl -XPUT -H "Content-Type: application/json" http://localhost:4985/omoidebase/ 
ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5 -d @place1.json 
curl -XPUT -H "Content-Type: application/json" http://localhost:4985/omoidebase/tom -d 
@profile1.json
構築5:クライアント同期 
Backet 
omoidebase 
Couchbase Server 
:8091 
Sync Gateway 
:4984 
アプリ 
Couchbase Lite 
Database 
omoidebase 
URL url = new URL("http://localhost:4984/omoidebase"); 
pull = database.createPullReplication(url); 
push = database.createPushReplication(url); 
Authenticator auth = new BasicAuthenticator(“tom”, “password”); 
pull.setAuthenticator(auth); 
push.setAuthenticator(auth); 
pull.start(); 
push.start(); 
Sync 
Function 
tom 
password 
place profile 
place profile
構築:Couchbase Serverのドキュメント 
32 
1.バケット作成 
なし 
2.Sync Gateway起動 
ID Content 
_sync:seq 
_sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === "profile… 
3.ユーザー作成 
ID Content 
_sync:seq 2 
_sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === ”profile… 
_sync:user:jerry { "name": "jerry", "all_channels": { }, "sequence": 2, "passwo… 
_sync:user:tom { "name": "tom", "all_channels": { }, "sequence": 1, "passwo…
構築:Couchbase Serverのドキュメント 
33 
4.マスタ系データインポート 
ID Content 
_sync:seq 7 
_sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === ”profile… 
_sync:user:jerry { "name": "jerry", "all_channels": { }, "sequence": 2, "passwo… 
_sync:user:tom { "name": "tom", "all_channels": { }, "sequence": 1, "passwo… 
ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5 { "_sync": { "rev": "1-375de787d53752736649d964197e7a41", "s… 
2C139CE5-9B5D-4836-97A3-B25AEC49D6FB { "_sync": { "rev": "1-22476c90d79e6724058271609f1a4408", "s… 
89B038CD-84A9-442c-95D1-0E22CAF8EB9E { "_sync": { "rev": "1-4867aafbf14a79607730e3e3f7de6257", "s… 
jerry { "_sync": { "rev": "1-c0888ab8cf936c83aaf36a10eaca1a8d", "s… 
tom { "_sync": { "rev": "1-009fa66f707d5e3eea7b2830cff0ea51", "s…
構築:Couchbase Serverのドキュメント 
34 
5.クライアント同期 
ID Content 
_sync:seq 7 
_sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === ”profile… 
_sync:user:jerry { "name": "jerry", "all_channels": { }, "sequence": 2, "passwo… 
_sync:user:tom { "name": "tom", "all_channels": { }, "sequence": 1, "passwo… 
ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5 { "_sync": { "rev": "1-375de787d53752736649d964197e7a41", "s… 
2C139CE5-9B5D-4836-97A3-B25AEC49D6FB { "_sync": { "rev": "1-22476c90d79e6724058271609f1a4408", "s… 
89B038CD-84A9-442c-95D1-0E22CAF8EB9E { "_sync": { "rev": "1-4867aafbf14a79607730e3e3f7de6257", "s… 
jerry { "_sync": { "rev": "1-c0888ab8cf936c83aaf36a10eaca1a8d", "s… 
tom { "_sync": { "rev": "1-009fa66f707d5e3eea7b2830cff0ea51", "s…
おもいでノート 
35 
Sync Function
Configuration Files 
{ 
"interface": ":4984", 
"adminInterface": ":4985", 
"log": [ 
"REST" 
], 
"databases": { 
"omoidebase": { 
"server": "http://localhost:8091", 
"bucket": "omoidebase", 
"sync": ` function(doc, oldDoc) { 
if (doc.type === "profile") { 
if (doc.places) { 
for (var i = 0; i < doc.places.length; i++) { 
access(doc.name, doc.places[i]); 
} 
} 
access(doc.name, doc.name); 
channel(doc.name); 
} else if (doc.type === "comment") { 
channel(doc.place); 
} else if (doc.type === "place") { 
channel(doc._id); 
} 
}` 
} 
} 
} 
36
Sync Function API 
37 
主な関数 
関数名引数説明 
throw forbiddenプロパティを含むエラーオブジェクト例外の送出 
requireUser username(文字列または文字列の配列) ユーザー名が引数に一致または配列の場合は含まれなければ例外を送出 
requireRole rolename(文字列または文字列の配列) ユーザーのロールが引数に一致または配列の場合は含まれなければ例外を送 
出 
requireAccess channels(文字列または文字列の配列) ユーザーが引数のチャネルのうち少なくとも一つへのアクセスを有していなけ 
れば例外を送出 
channel name(文字列または文字列の配列。nullやundefinedでも可) 引数に指定されたチャネルにドキュメントをルーティングします 
access username(文字列または文字列の配列。nullやundefinedでも可), 
channelname(文字列または文字列の配列。nullやundefinedでも可) 
ユーザーにチャネルへのアクセス権を付与します 
role username(文字列または文字列の配列。nullやundefinedでも可), 
rolename(文字列または文字列の配列。nullやundefinedでも可) 
ユーザーにロールを付与します 
http://developer.couchbase.com/mobile/develop/guides/sync-gateway/sync-function-api-guide/index.html 
重要なのは 
channelとaccess
場所 
チャネル 
ADAA8D9E-26C4-46F8-9A 
39-78EFD6DDC3F5 
{ 
"type" : "place", 
"code" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", 
"name" : "Westin San Francisco", 
"remark": "Couchbase Connect 2014 on Oct 6, 2014 in San Francisco", 
"location": { 
チャネル 
89B038CD-84A9-442c-95 
D1-0E22CAF8EB9E 
チャネル 
2C139CE5-9B5D-4836-97 
A3-B25AEC49D6FB 
"latitude": 37.7876643, 
"longitude": -122.4090627 
}, 
"image" : "画像 (base64文字列)" 
} 
if (doc.type === "place") { 
channel(doc._id); 
} 
場所場所場所
プロフィール 
if (doc.type === "profile") { 
if (doc.places) { 
for (var i = 0; i < doc.places.length; i++) { 
access(doc.name, doc.places[i]); 
} 
} 
access(doc.name, doc.name); 
channel(doc.name); 
} 
プロフィール場所プロフィール場所 
チャネル 
tom 
チャネル 
jerry 
チャネル 
ADAA8D9E-26C4-46F8-9 
A39-78EFD6DDC3F5 
tom jerry 
チャネル 
89B038CD-84A9-442c-95 
D1-0E22CAF8EB9E 
{ 
"type" : "profile", 
"name" : "tom", 
"places" : [ 
"ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", 
"89B038CD-84A9-442c-95D1-0E22CAF8EB9E" 
] 
}
コメント 
{ 
"type" : "comment", 
"place" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", 
"created_at" : "2014-11-17T13:56:52+09:00", 
"contents" : "内容", 
"image": "画像 (base64文字列)" 
} 
if (doc.type === "comment") { 
channel(doc.place); 
} 
コメントコメントコメント 
チャネル 
ADAA8D9E-26C4-46F8-9 
A39-78EFD6DDC3F5 
チャネル 
89B038CD-84A9-442c-95 
D1-0E22CAF8EB9E 
チャネル 
2C139CE5-9B5D-4836-97 
A3-B25AEC49D6FB
ポイント 
•チャネルの範囲を決める 
•ドキュメントにプロフィール情報を持つ 
チャネル 
ADAA8D9E-26C4-46F8- 
9A39-78EFD6DDC3F5 
場所 
コメント 
コメント 
コメント 
コメント
42 
That's all.

More Related Content

Couchbase MeetUP Tokyo - #11 Omoidenote

  • 1. 1 Couchbase MeetUP Tokyo - #11
  • 2. 自己紹介 2 •木次 恭一 •Twitter: @kyoichi_kitsugi  •ウイングソリューションズ(株) •仕事ではJavaがメイン •最近では Sencha Touch, ElasticSearchなど
  • 3. Couchbase Mobileとの出会い 3 MongoDB CouchDB TouchDB Couchbase Server Sync Gateway Couchbase Lite CouchDB NoSQL に興味 JSON 大好き モバイル 大好き
  • 4. Couchbase Mobile Hackathon 4 ハッカソン開催 •2014年9月7日開催 •向上心溢れる暇な人が集結 •Couchbase Liteを利用したアプリを作成 •優勝したら一人だけサンフランシスコに行ける
  • 5. Couchbase Mobile Hackathon 5 ROUND 1 FIGHT
  • 6. Couchbase Mobile Hackathon 6 TIME OVER 5時間じゃ厳しいっす!!
  • 7. Couchbase Mobile Hackathon 7 ヒソ( ´д)ヒソ(´д`)ヒソ(д` )ヒソ 審査中 ネェ、キイタ?( ´д)オクサン(д` )アラヤダワァ
  • 9. Couchbase Mobile Hackathon 9 勝因をしいてあげるなら •チームの人数が多かった •プレゼン資料が良かった •画面数が一番多かった
  • 10. おもいでノート 10 行ったことがある場所A B Tom Jerry 行ったことがない場所C 行った事がある場所は 自宅で閲覧・更新が可能 その場所に行かないと 何も出来ない
  • 11. おもいでノート 11 デモ https://github.com/kitsugi/omoidebase
  • 13. Couchbase Connect 13 •2014年10月6日~7日開催 •サンフランシスコ •全米No1と僕が思ったNoSQLカンファレンス •スタバのコーヒーが飲み放題
  • 21. Document種別 21 場所 place コメント comment プロフィール コメント コメント tom comment comment 場所 place コメント comment コメント comment プロフィール jerry
  • 22. 場所 { "type" : "place", "code" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", "name" : "Westin San Francisco", "remark": "Couchbase Connect 2014 on Oct 6, 2014 in San Francisco", "location": { "latitude": 37.7876643, "longitude": -122.4090627 }, "image" : "画像 (base64文字列)" }
  • 23. コメント { "type" : "comment", "place" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", "created_at" : "2014-11-17T13:56:52+09:00", "contents" : "内容", "image": "画像 (base64文字列)" }
  • 24. プロフィール { "type" : "profile", "name" : "tom", "places" : [ "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", "89B038CD-84A9-442c-95D1-0E22CAF8EB9E" ] }
  • 26. 構成図 Couchbase Server Sync Gateway おもいでノート (Couchbase Lite) cURL等 :8091 Backet omoidebase :4985 :4984 User, Roleの作成・削除 マスタ投入 おもいでノート (Couchbase Lite) 26 コメント作成コメント作成
  • 27. 構築1:バケット作成 Couchbase Server :8091 Backet omoidebase Admin Console等
  • 28. 構築2:Sync Gateway起動 Backet omoidebase Couchbase Server :8091 Sync Gateway Terminal等 ./sync_gateway config.json { "interface": ":4984", "adminInterface": ":4985", "log": [ "REST" ], "databases": { "omoidebase": { "server": "http://localhost:8091", "bucket": "omoidebase", "sync": ` function(doc, oldDoc) { if (doc.type === "profile") { if (doc.places) { for (var i = 0; i < doc.places.length; i++) { access(doc.name, doc.places[i]); } } access(doc.name, doc.name); channel(doc.name); } else if (doc.type === "comment") { channel(doc.place); } else if (doc.type === "place") { channel(doc._id); } }` } } } ※データーベースは複数定義可能 :4984 :4985 Sync Function
  • 29. 構築3:ユーザー作成 Backet omoidebase Couchbase Server :8091 Sync Gateway :4985 cURL等 tom password curl -XPOST -H "Content-Type: application/json" http://localhost:4985/omoidebase/ _user/ -d @user1.json { "name": "tom", "password": "password" }
  • 30. 構築4:マスタ系データインポート Backet omoidebase Couchbase Server :8091 Sync Gateway :4985 cURL等 場所プロフィール curl -XPUT -H "Content-Type: application/json" http://localhost:4985/omoidebase/ ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5 -d @place1.json curl -XPUT -H "Content-Type: application/json" http://localhost:4985/omoidebase/tom -d @profile1.json
  • 31. 構築5:クライアント同期 Backet omoidebase Couchbase Server :8091 Sync Gateway :4984 アプリ Couchbase Lite Database omoidebase URL url = new URL("http://localhost:4984/omoidebase"); pull = database.createPullReplication(url); push = database.createPushReplication(url); Authenticator auth = new BasicAuthenticator(“tom”, “password”); pull.setAuthenticator(auth); push.setAuthenticator(auth); pull.start(); push.start(); Sync Function tom password place profile place profile
  • 32. 構築:Couchbase Serverのドキュメント 32 1.バケット作成 なし 2.Sync Gateway起動 ID Content _sync:seq _sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === "profile… 3.ユーザー作成 ID Content _sync:seq 2 _sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === ”profile… _sync:user:jerry { "name": "jerry", "all_channels": { }, "sequence": 2, "passwo… _sync:user:tom { "name": "tom", "all_channels": { }, "sequence": 1, "passwo…
  • 33. 構築:Couchbase Serverのドキュメント 33 4.マスタ系データインポート ID Content _sync:seq 7 _sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === ”profile… _sync:user:jerry { "name": "jerry", "all_channels": { }, "sequence": 2, "passwo… _sync:user:tom { "name": "tom", "all_channels": { }, "sequence": 1, "passwo… ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5 { "_sync": { "rev": "1-375de787d53752736649d964197e7a41", "s… 2C139CE5-9B5D-4836-97A3-B25AEC49D6FB { "_sync": { "rev": "1-22476c90d79e6724058271609f1a4408", "s… 89B038CD-84A9-442c-95D1-0E22CAF8EB9E { "_sync": { "rev": "1-4867aafbf14a79607730e3e3f7de6257", "s… jerry { "_sync": { "rev": "1-c0888ab8cf936c83aaf36a10eaca1a8d", "s… tom { "_sync": { "rev": "1-009fa66f707d5e3eea7b2830cff0ea51", "s…
  • 34. 構築:Couchbase Serverのドキュメント 34 5.クライアント同期 ID Content _sync:seq 7 _sync:syncdata { "Sync": " function(doc, oldDoc) {n if (doc.type === ”profile… _sync:user:jerry { "name": "jerry", "all_channels": { }, "sequence": 2, "passwo… _sync:user:tom { "name": "tom", "all_channels": { }, "sequence": 1, "passwo… ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5 { "_sync": { "rev": "1-375de787d53752736649d964197e7a41", "s… 2C139CE5-9B5D-4836-97A3-B25AEC49D6FB { "_sync": { "rev": "1-22476c90d79e6724058271609f1a4408", "s… 89B038CD-84A9-442c-95D1-0E22CAF8EB9E { "_sync": { "rev": "1-4867aafbf14a79607730e3e3f7de6257", "s… jerry { "_sync": { "rev": "1-c0888ab8cf936c83aaf36a10eaca1a8d", "s… tom { "_sync": { "rev": "1-009fa66f707d5e3eea7b2830cff0ea51", "s…
  • 36. Configuration Files { "interface": ":4984", "adminInterface": ":4985", "log": [ "REST" ], "databases": { "omoidebase": { "server": "http://localhost:8091", "bucket": "omoidebase", "sync": ` function(doc, oldDoc) { if (doc.type === "profile") { if (doc.places) { for (var i = 0; i < doc.places.length; i++) { access(doc.name, doc.places[i]); } } access(doc.name, doc.name); channel(doc.name); } else if (doc.type === "comment") { channel(doc.place); } else if (doc.type === "place") { channel(doc._id); } }` } } } 36
  • 37. Sync Function API 37 主な関数 関数名引数説明 throw forbiddenプロパティを含むエラーオブジェクト例外の送出 requireUser username(文字列または文字列の配列) ユーザー名が引数に一致または配列の場合は含まれなければ例外を送出 requireRole rolename(文字列または文字列の配列) ユーザーのロールが引数に一致または配列の場合は含まれなければ例外を送 出 requireAccess channels(文字列または文字列の配列) ユーザーが引数のチャネルのうち少なくとも一つへのアクセスを有していなけ れば例外を送出 channel name(文字列または文字列の配列。nullやundefinedでも可) 引数に指定されたチャネルにドキュメントをルーティングします access username(文字列または文字列の配列。nullやundefinedでも可), channelname(文字列または文字列の配列。nullやundefinedでも可) ユーザーにチャネルへのアクセス権を付与します role username(文字列または文字列の配列。nullやundefinedでも可), rolename(文字列または文字列の配列。nullやundefinedでも可) ユーザーにロールを付与します http://developer.couchbase.com/mobile/develop/guides/sync-gateway/sync-function-api-guide/index.html 重要なのは channelとaccess
  • 38. 場所 チャネル ADAA8D9E-26C4-46F8-9A 39-78EFD6DDC3F5 { "type" : "place", "code" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", "name" : "Westin San Francisco", "remark": "Couchbase Connect 2014 on Oct 6, 2014 in San Francisco", "location": { チャネル 89B038CD-84A9-442c-95 D1-0E22CAF8EB9E チャネル 2C139CE5-9B5D-4836-97 A3-B25AEC49D6FB "latitude": 37.7876643, "longitude": -122.4090627 }, "image" : "画像 (base64文字列)" } if (doc.type === "place") { channel(doc._id); } 場所場所場所
  • 39. プロフィール if (doc.type === "profile") { if (doc.places) { for (var i = 0; i < doc.places.length; i++) { access(doc.name, doc.places[i]); } } access(doc.name, doc.name); channel(doc.name); } プロフィール場所プロフィール場所 チャネル tom チャネル jerry チャネル ADAA8D9E-26C4-46F8-9 A39-78EFD6DDC3F5 tom jerry チャネル 89B038CD-84A9-442c-95 D1-0E22CAF8EB9E { "type" : "profile", "name" : "tom", "places" : [ "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", "89B038CD-84A9-442c-95D1-0E22CAF8EB9E" ] }
  • 40. コメント { "type" : "comment", "place" : "ADAA8D9E-26C4-46F8-9A39-78EFD6DDC3F5", "created_at" : "2014-11-17T13:56:52+09:00", "contents" : "内容", "image": "画像 (base64文字列)" } if (doc.type === "comment") { channel(doc.place); } コメントコメントコメント チャネル ADAA8D9E-26C4-46F8-9 A39-78EFD6DDC3F5 チャネル 89B038CD-84A9-442c-95 D1-0E22CAF8EB9E チャネル 2C139CE5-9B5D-4836-97 A3-B25AEC49D6FB
  • 41. ポイント •チャネルの範囲を決める •ドキュメントにプロフィール情報を持つ チャネル ADAA8D9E-26C4-46F8- 9A39-78EFD6DDC3F5 場所 コメント コメント コメント コメント