flask-dmango
์ฝ๋ฉ์ ์ต์ํํ์ฌ ์๋น์ค๊ฐ๋ฐ์ ์ง์ค ํ ์ ์๋๋ก ์ง์ํ๊ธฐ ์ํด, ๋๋ง๊ณ ๋ ํน๋ณํ ์ฝ๋ฉ์ด๋ ๋ ธ๋ ฅ์์ด, restful-api์ admin๊ธฐ๋ฅ์ ์ ๊ณตํ๋๊ฒ์ ๋ชฉ์ ์ผ๋ก ํฉ๋๋ค. ์ฐธ๊ณ ๋ก, ๋๋ง๊ณ ๋ flask์ mongodb(flask.ext.pymongo)๋ฅผ ์ฐ๋ํ์ฌ ๊ตฌํํ์์ต๋๋ค.
๋จ, 0.0.3 ๋ฒ์ ์์๋ admin๊ธฐ๋ฅ์ ๊ฐ๋ฐ๋์ง ์์์ต๋๋ค.
- install
pip install flask-dmango
1. ์๊ฐ
restful API๋ ๊ณต์ง !
์๋์ ๊ฐ์ด mongodb์ ์ ์์ ๋ณด๋ง ์ ๋ ฅํด์ฃผ๋ฉด, ์๋์ ์ฃผ์๋ก restfulํํ์ api์ฌ์ฉ์ด ๊ฐ๋ฅํด์ง๋๋ค. http://127.0.0.1:5000/dmango/server1
from flask import Flask, current_app, Blueprint, request
from flask.ext.dmango import Dmango
app = Flask(__name__)
dmango = Dmango(app)
dmango.register_mongodb('server1', URI = 'mongodb://user_id:password@ds051459.mongolab.com:51459/database')
if __name__ == '__main__':
app.run()
MongoDB์ ํธ๋ฆฌํ ์ง์
register_mongodb๋ก ๋ฑ๋กํ ๋ชฝ๊ณ ๋๋น๋ Dmango.find_mongodb() ์ ํตํด blueprint๋ฅผ ์ด์ฉํ์ฌ ๊ตฌํํ๋ค๋ฉด, ๋ชฝ๊ณ ๋๋น์ connection์ ์ฝ๊ฒ ๋ถ๋ฌ ์ฌ์ ์์ต๋๋ค.
from flask import Blueprint
from flask.ext.dmango import Dmango
bp = Blueprint('name1', __name__)
@bp.route('/')
def index():
db = Dmango.find_mongodb('server1')
result = db["collection_name"].find({"title": "์ ๋ชฉ"})
render_template('index.html', data=result, total=count)
ํธ๋ฆฌํ ์ฟผ๋ฆฌ ์์ฑ ์ง์
๋ณต์กํ ๋ชฝ๊ณ ๋๋น์ jsonํํ์ ์ฟผ๋ฆฌ๋ฅผ ๋ช๊ฐ์ง ๊ท์น์ ํตํด ๋ ์ฝ๊ฒ ์์ฑ ํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ์ด ๊ท์น์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ restful api๋ฅผ ์ฌ์ฉํ ๋ ๊ผญ ์์๋ฌ์ผ ํฉ๋๋ค
from flask.ext.dmango import DmangoQueryBuilder
b = DmangoQueryBuilder()
b.query("title__ilike", 'apple')
b.query("price__gte:int", 5000)
b.query("code__in", ['food', 'digital'])
print b()
==> {'price': {'$gte': 5000}, 'code': {'$in': ['food', 'digital']}, 'title': /apple/i }
2. RestFul API (๋ค์ด๊ฐ๊ธฐ์ )
๋๋ง๊ณ ์ ResultFul API ์ฃผ์ํ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
http://127.0.0.1:5000/dmango/server๋ช )
2.1 DB๋ฆฌ์คํธ ๋ณด๊ธฐ (์:์๋ฒ๋ช ๋ง ๋ฃ์์ ๊ฒฝ์ฐ๋ ํด๋น ์๋ฒ์ ์กด์ฌํ๋ database ๋ชฉ๋ก์ ๋์ ธ์ค๋๋ค.
{
"status": 200,
"api_name": "show_dbs",
"db_names": [
"cx",
"sada9_dev",
"local"
],
"msg": "์ฑ๊ณต",
"total": 3,
"server": "sada9_api"
}
2.2 collection ๋ฆฌ์คํธ ๋ณด๊ธฐ
์: http://127.0.0.1:5000/dmango/server๋ช .db๋ช ์๋ฒ๋ช ๊ณผ DB๋ช ์ ๋ฃ์์ ๊ฒฝ์ฐ๋ ํด๋น ์๋ฒ์ DB์ ์กด์ฌํ๋ collection ๋ชฉ๋ก์ ๋์ ธ์ค๋๋ค.
{
"status": 200,
"api_name": "show_dbs",
"db_names": [
"sada9_dev",
"local"
],
"msg": "์ฑ๊ณต",
"total": 3,
"server": "sada9_api"
}
2.3 ๋ช ๋ น์ด ๋ณด๊ธฐ
์: http://127.0.0.1:5000/dmango/server๋ช .db๋ช .collection๋ช ์๋ฒ๋ช ๊ณผ DB๋ช ๊ทธ๋ฆฌ๊ณ collection๋ช ์ ๋ชจ๋ ์ ๋ ฅํ ๊ฒฝ์ฐ๋ ๋๋ง๊ณ ์์ ์ง์๊ฐ๋ฅํ ๋ช ๋ น์ด ์ ๋ณด๊ฐ ๋ณด์ฌ์ง๋๋ค.
{
"result": [
{
"name": "param",
"comment": "ํ๋ผ๋ฏธํฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ง๋ค์ด ์ง๋์ง ํ
์คํธํ๊ธฐ ์ํด์ ์ฌ์ฉ",
"url": "./server1.sada9_dev.testdb/param"
},
{
"name": "find_one",
"comment": "ํ๊ฑด๋ง ๊ฒ์ํ ๋ ์ฌ์ฉํ๋ค. ๋จ, _id ์กฐ๊ฑด์ด ์์ผ๋ฉด ๋๋จธ์ง๋ ๋ฌด์๋จ",
"url": "./server1.sada9_dev.testdb/find_one"
},
... ์๋ต ....
{
"name": "string_group",
"comment": "ํน์ ํ๋๋ฅผ ๊ทธ๋ฃนํํ์ฌ ์นด์ดํ
ํด์ค๋ค. _group= ์ด๋ผ๋ ๊ฐ์ ์ฌ์ฉํ๋ค.",
"url": "./server1.sada9_dev.testdb/string_group"
}
],
"status": 200,
"api_name": "api_list",
"msg": "์ฑ๊ณต",
"time(ms)": 0,
"total": 11
}
3. RestFul API (๋ช ๋ น์ด์๊ธฐ)
๋๋ง๊ณ ์ ResultFul API ์์ "์๋ฒ.๋๋น.์ฝ๋ ์ "์ ๋ชจ๋ ์ ๋ ฅํ ๊ฒฝ์ฐ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ์ง์๋๋ ๋ช ๋ น์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
๋ช ๋ น์ด | ์ค๋ช | ์์ |
---|---|---|
param | ํ๋ผ๋ฏธํฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ง๋ค์ด ์ง๋์ง ํ ์คํธํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ค. | . |
find_one | ํ๊ฑด๋ง ๊ฒ์ํ ๋ ์ฌ์ฉํ๋ค. ๋จ, _id ์กฐ๊ฑด์ด ์์ผ๋ฉด ๋๋จธ์ง๋ ๋ฌด์๋๋ค ํน์ด ์ฌํญ์ผ๋ก๋ _page_num=1 _page_size=10 ๊ฐ์ ํ์ด์ง ๊ธฐ๋ฅ๋ ์ ์ฉ๊ฐ๋ฅํ๋ค. | |
find | ์ผ๋ฐ์ ์ธ ๊ฒ์์ ํ ๋ ์ฌ์ฉํ๋ค | . |
count | ๊ฒ์๊ฒฐ๊ณผ๊ฐ ๋ช๊ฑด์ธ์ง ํ์ธํ๊ธฐ์ํด ์ฌ์ฉ | . |
insert | ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ์ํด ์ฌ์ฉํ๋ค. ๋จ, ํ๋๋ช ์ด _๋ก ์์๋๋ ๊ฐ์ ๋ฌด์๋๋ค | . |
save | ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ์ํด ์ฌ์ฉํ๋ค. insert ์์ ์ฐจ์ด์ ์ _id ๊ฐ ํ์ฉ๋๋ฉฐ, ๊ฐ์ _id๋ฅผ ๋ง๋๋ฉด update ์ฒ๋ฆฌ๋๋ค | . |
update | _id๋ก 1๊ฑด์ ๋ฐ์ดํฐ๋ง ์ฐพ์ update ๊ฐ ๊ฐ๋ฅํ๋ค. (์ฆ, where์กฐ๊ฑด์ _id๋ง ๊ฐ๋ฅํ๊ณ ๋๋จธ์ง๋ ๋ณ๊ฒฝ๋๋ ๊ฐ์ด๋ค) | . |
remove | _id ๋ก ์ฐพ์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ค (์ฌ๋ฌ๊ฑด์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋๊ฒ์ ์ง์ํ์ง ์๋๋ค) | . |
push | _id ๋ก ์ฐพ์ ๋ฐ์ดํฐ์์ list ํ์ ์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ append ํ ๋ ์ฌ์ฉํ๋ค. | id=id๊ฐ&cate_nm=์ถ๊ฐํ ๊ฐ |
inc | _id ๋ก ์ฐพ์ ๋ฐ์ดํฐ์์ ํน์ ํ๋์ ๊ฐ์ ์ฆ๊ฐ์์ผ์ค๋ค. ๋ณดํต ์กฐํ์ updateํ ๋ ์ฌ์ฉํ๋ค. | /dmango/server.db.collection/inc?id=id๊ฐ&clk_cnt=1 |
string_group | ํ๋๋ฅผ ๊ทธ๋ฃนํํ์ฌ ์นด์ดํ ํด์ค๋ค. ๊ทธ๋ฃน๋์์ด ๋๋ ํ๋๋ _group ์ด๋ผ๋ ์์ฝ์ด๋ฅผ ์ฌ์ฉํ๋ฉฐ, listํ์ ์ ํ๋๋ฅผ ํ์ด์ ๊ทธํํ ํด์ผ ํ๋ค๋ฉด, _unwind ๋ผ๋ ์์ฝ์ด๊ฐ ์กด์ฌํ๋ค. | /dmango/server.db.collection/string_group?_group=cate_nm&_unwind=cate_nm |
4. Dmango ํ๋ผ๋ฏธํฐ ์๊ธฐ
๋๋ง๊ณ ์์๋ ์๋ฒ์์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ์ง ์๊ณ , GET ํํ๋ก ์ฌ์ฉ์๊ฐ ์ง์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ผ๋ก ์์ ๋กญ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋๊ฒ์ ์ง์ํ๋ค. ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ฐ์ดํฐ๋ฅผ ํํํ๋ "Dmangoํ๋ผ๋ฏธํฐ"์ ๋ํ ์ฌ์ฉ๋ฒ์ ์์์ผ ํ๋ค.
- ๊ตฌ์กฐ : ํ๋๋ช __๋ฉ์๋:ํ์ =๊ฐ
- ์์ : product__ilike:string=์ ์นด๋ด
4.1 ํ๋๋ช
mongodb์ ํ๋๋ช ์ ์๋ฏธํ๋ค. (์คํค๋ง์ ํ๋๋ช ์ ์๋ฏธํ๋ค.)
4.2 ๋ฉ์๋
๊ฒ์์กฐ๊ฑด์ ์คํผ๋ ์ด์ ์ ์๋ฏธํ๋ค. ๋ฐ์ดํฐ๋ฅผ like๊ฒ์ํ๊ฑฐ๋ ๋ฒ์ ๊ฒ์์ ํ๊ณ ์ถ์๋ ์ด์ฉํ๋ค.
๋ฉ์๋๋ช | ์ค๋ช |
---|---|
like | ์ข์ฐ์ ๋จ ๊ฒ์์ ์๋ฏธํ๋ค. like ๊ฒ์์ ์๊ฐํ๋ฉด ๋๋ค. |
ilike | like์ ์ ์ฌํ๊ณ , ๋ค๋ฅธ์ ์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋๋ค |
gt | ํน์ ๊ฐ๋ณด๋ค ํฌ๋ค๋ฅผ ์๋ฏธํ๋ค. (val > 100) |
lt | ํน์ ๊ฐ๋ณด๋ค ์๋ค๋ฅผ ์๋ฏธํ๋ค. (val < 100) |
gte | ํน์ ๊ฐ๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์์ ์๋ฏธํ๋ค (val >= 100) |
lte | ํน์ ๊ฐ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์์ ์๋ฏธํ๋ค (val <= 100) |
in | ๊ฐ์ด ํฌํจ๋์๋์ง ์๋ฏธํ๋ค. val in (๊ฐ1, ๊ฐ2 ...) |
nin | ๊ฐ์ด ํฌํจ๋์ง ์์๋์ง ์๋ฏธํ๋ค. ๋จ N๊ฐ์ ๊ฐ์ด ์ง์๋๋ค. val not in (๊ฐ1, ๊ฐ2...) |
ne | not equals ( val != ๊ฐ) |
startswith | ๋ฌธ์์ด์ด ํน์ ๊ฐ์ผ๋ก ์์ํ๋์ง ์ฐพ๋๋ค |
endswith | ๋ฌธ์์ด์ด ํน์ ๊ฐ์ผ๋ก ๋๋๋์ง ์ฐพ๋๋ค |
istartswith | startswith์์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋๋ค |
iendswith | endswith์์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋๋ค |
between | ๋ฒ์๊ฐ์ ์๋ฏธํ๋ค. gte์ lte๋ฅผ ์ฌ์ฉํ๋๊ฒ๊ณผ ๋์ผํ๋ค. ์ ์ฉํ ์ ์ value์ ํฌ๊ธฐ์ ๋ฐ๋ผ gte์ lte๊ฐ ์์์ ๋ถ์ธ๋ค๋ ์ ์ด ๋ค๋ฅด๋ค. price__between=200&price__between=100 ==> {price: {$lte:"200", $gte:"100"} |
price__between=50&price__between=110 ==> {price: {$lte:"50", $gte:"110"} |
์๋ตํ์๋๋ exact์ ๊ฐ๋ค๊ณ ๋ณด๋ฉด๋๋ฉฐ, insert, update๋ฅผ ์ํด์ ์ฌ์ฉ๋๋ ํ๋๋ ๋ฉ์๋๋ฅผ ๋ถ์ด๋ฉด ์๋๋ค.
4.3 ํ์ (๋ฐ์ดํฐ ํ์ )
๋ฐ์ดํฐ ํ์ ์ ์๋ฏธํ๋ค. int, string ๊ฐ์ ๋ฐ์ดํฐ ํ์ ์ ์๋ฏธํ๋ค. request๋ฐ๋ ๊ฐ์์๋ ๋ฐ์ดํฐ ํ์ ์ ์์ ์๊ณ , ๋ชฝ๊ณ ๋๋น์์ ๋ฐ์ดํฐ ํ์ ์ ์ง์ ํด์ผ ํ๋ ๊ฒฝ์ฐ๋ฅผ ์ํด ์ฌ์ฉ๋๋ค. ์๋ฅผ ๋ค์ด, price=100 ์ผ๋ก ๊ฐ์ ๋ฐ์ผ๋ฉด, 100์ stringํ์ผ๋ก ๋ฐ๊ฒ๋์ด ์ซ์ํ ๊ฐ๊ณผ ๋น๊ตํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์๋๋ค. ์ด๋ด๋, price:int=100 ๊ณผ ๊ฐ์ด ํ์ ์ ์ง์ ํด ์ค ์ ์๋ค.
ํ๋ํ์ | ์ค๋ช |
---|---|
int | ์ ์ํ ์ซ์ |
long | ์ ์ํ ์ซ์ |
float | ์์ซ์ ํ ์ซ์ |
string, text, str | ๋ฌธ์์ด์ ์๋ฏธํ๋ค. |
json | json์ผ๋ก ๋ณํํ๋ค. ํ๋๋ช ์ ๊ผญ "" ๋ฅผ ๋ฃ์ด ๊ท์น์ ๋ง์ถฐ์ผํ๋ค. |
datetime | datetimeํ์ผ๋ก ๋ณํํ๋ค. yyyymmddhhmiss ํํ์ ๋ฌธ์์ด๋ก ํํํ ๊ฐ์ ๋ณํํ๋ค. |
list | ์ฝค๋ง(,) ๋ก ๊ตฌ๋ถ๋ ๋ฌธ์์ด์ list๋ก ๋ณํํ๋ค. (๋ด๋ถ์ ์ผ๋ก๋ split(",") ํ๋ค๊ณ ๋ณด๋ฉด๋๋ค) |
dict | json๊ณผ ๋์ผํ๋ค |
oid | ObjectID ํ์ ์ ์๋ฏธํ๋ค |
4.4.๊ฐ ์ ์ฅ๋ ๊ฐ์ ์๋ฏธํ๋ค. GETํํ์์ ๋ฐ๋ value์ ๋์ผํ๋ค. ํน๋ณํ ๊ธฐ๋ฅ์ผ๋ก๋ $today ๊ฐ ์กด์ฌํ๋ค. (yyyymmdd ํํ์ ์ค๋๋ ์ง๋ฅผ ๋ฌธ์์ด๋ก ์๋๋ณํ๋๋ค.)
- ์์ฝ์ด ๋๋ง๊ณ ์ ํ๋ํํ์์๋ ์์ฝ์ด๋ _๋ก ์์ํ๋ ๊ฐ์ด๋ค. ์ฃผ์ find๋ string_group ๊ฐ์ ์กฐํํ ๋ ์์ด์ ์ฌ์ฉํ๋๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
- _page_num : ํ์ด์ง์ฒ๋ฆฌ๋ฅผ ํ ๋ ์ฌ์ฉ๋๋ค. (string_group, find ๋ช ๋ น์์ ์ฌ์ฉ)
- _page_size: ํ์ด์ง์ฒ๋ฆฌ๋ฅผ ํ ๋ ์ฌ์ฉ๋๋ค. (string_group, find ๋ช ๋ น์์ ์ฌ์ฉ)
- _start_offset : ํ์ด์ง์ฒ๋ฆฌ๋ฅผ ํ ๋ ์ฌ์ฉ๋๋ค. _page_num๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋ค๋ฉด offset๊ฐ์ด ์ฐ์ ๋๋ค.
- _end_offset : ํ์ด์ง์ฒ๋ฆฌ๋ฅผ ํ ๋ ์ฌ์ฉ๋๋ค. _page_size๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋ค๋ฉด offset๊ฐ์ด ์ฐ์ ๋๋ค.
- _fields : db์ฟผ๋ฆฌ์ select๋ฌธ๊ณผ ๊ฐ๋ค. ์กฐํํ ๋์์ ํ๋๋ฅผ ์ ์ฝํ ๋ ์ฌ์ฉ๋๋ค. &_fields=product_nm,price ๋ฅผ ์ถ๊ฐํ๋ฉด ํด๋น ํ๋์ ๊ฒฐ๊ณผ๋ง ๋ฆฌํด๋๋ค.
- _options: ๋๋ง๊ณ ์ ์ต์ ์ ์๋ฏธํ๋ค. ํ์ฌ๋ json๊ฒฐ๊ณผ์ ๊ฐํ์ ํ ์ง ์ํ ์ง ์กฐ์ ํ๋ indent๋ง ์กด์ฌํ๋ค. (์: _options=indent:true )
- _group : ๊ทธ๋ฃนํํ ํ๋๋ฅผ ์๋ฏธํ๋ค. string_group ์์๋ง ์ฌ์ฉ๋๋ค.
- _unwind : ๊ทธ๋ฃนํํ ์์ listํ์ ์ด์ด์ ์์ดํ ์ ํ์ด์ผํ ํ๋๋ฅผ ์๋ฏธํ๋ค. string_group ์์๋ง ์ฌ์ฉ๋๋ค.
- _exclude_query_fields : ์ฟผ๋ฆฌ๋ก ์ ๋๋๋ฉด ์๋๋ ํ๋๋ฅผ ์๋ฏธํ๋ค. ์๋ฅผ ๋ค์ด, ๋ก๊น ๋ชฉ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋๋ฏธ๊ฐ์ด ์ฟผ๋ฆฌ๋ก ์ ๋๋์ง ์๊ธฐ๋ฅผ ํฌ๋งํ ๋ ์ฌ์ฉํ๋ค. (์: _exclude_query_fields=user_id)
- _sort : ์ ๋ ฌ์ ํ ๋ ์ฌ์ฉ๋๋ค. ํ๋๋ช __desc , ํ๋๋ช __asc ํํ๋ก ์ฌ์ฉํ๋ค (์: _sort=price__desc )
6. ์์ ๋ก ๋ณด๋ restful API ์ฌ์ฉ
6.1 price ํ๋๋ ์ซ์๊ฐ์ด๊ณ 1000 ~ 2000์ธ ๊ฐ์ ์กฐํํ๊ณ ์ ํ ๋ ==> /find?price__gte:int=1000&price__lte:int=2000
6.2 title์ "๊ตฌ๋"๊ฐ ํฌํจ๋ ์ ํ์ ์ฐพ์ category๋ก ๊ทธ๋ฃนํ ==> /string_group?title__ilike=๊ตฌ๋&_group=category
6.3 title์ด๋ category์ ์๋ฅ๊ฐ ํฌํจ๋ ์ํ์ 100๊ฐ๋ง ๋ณด๊ณ ์ ํ ๋ ==> /find?title,category__ilike=์๋ฅ&_page_size=100
6.4 "6.3"์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ธฐ์ข๊ฒ ๊ฐํํด์ ๋ณด๊ณ ์ถ์๋ ==> /find?title,category__ilike=์๋ฅ&_page_size=100&_options=indent:true
6.5 {title: "์ ์นด๋ด ์ ํ", price: 4500, cate_nm : ["์ํ์ฉํ", "ํน๊ฐ"], cate_cd : [4, 6]} ์ ์ ์ฅํ๋ ค๋ฉด? ==> /insert?title=์ ์นด๋ด ์ ํ&price:int=4500&cate_nm:list=์ํ์ฉํ,ํน๊ฐ&cate_cd:json=[4, 6] ==> /insert?title=์ ์นด๋ด ์ ํ&price:int=4500&cate_nm=์ํ์ฉํ&&cate_nm=ํน๊ฐ&cate_cd:int=4&cate_cd:int=6 ==> ๋ค์ํ ํํ์ด ๋ ์กด์ฌํจ.