design-documents.coffee 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. # Design документы для CouchDB с поддержкой мультидоменности и мультиязычности
  2. module.exports =
  3. # Design документ для настроек доменов
  4. domains:
  5. version: "3.0"
  6. views:
  7. # Все настройки доменов
  8. all_domains:
  9. map: ((doc) ->
  10. if doc.type is 'domain_settings'
  11. emit(doc.domain, doc)
  12. ).toString()
  13. # Активные домены
  14. active_domains:
  15. map: ((doc) ->
  16. if doc.type is 'domain_settings' and doc.active is true
  17. emit(doc.domain, doc)
  18. ).toString()
  19. # Домены по приоритету
  20. by_priority:
  21. map: ((doc) ->
  22. if doc.type is 'domain_settings' and doc.active is true
  23. emit(doc.priority or 0, doc)
  24. ).toString()
  25. # Design документ для блог постов с мультидоменностью и мультиязычностью
  26. blog_posts:
  27. version: "3.0"
  28. views:
  29. # Все опубликованные блог посты с фильтром по домену и языку
  30. published:
  31. map: ((doc) ->
  32. if doc.type is 'blog_post' and doc.status is 'published'
  33. domain = doc.domain or 'default'
  34. language = doc.language or 'ru'
  35. emit([domain, language, doc.created_at], doc)
  36. ).toString()
  37. # Блог посты по тегам с фильтром по домену и языку
  38. by_tag:
  39. map: ((doc) ->
  40. if doc.type is 'blog_post' and doc.status is 'published' and doc.tags
  41. domain = doc.domain or 'default'
  42. language = doc.language or 'ru'
  43. for tag in doc.tags
  44. emit([domain, language, tag, doc.created_at], doc)
  45. ).toString()
  46. # Блог посты по автору с фильтром по домену и языку
  47. by_author:
  48. map: ((doc) ->
  49. if doc.type is 'blog_post' and doc.status is 'published'
  50. domain = doc.domain or 'default'
  51. language = doc.language or 'ru'
  52. emit([domain, language, doc.author, doc.created_at], doc)
  53. ).toString()
  54. # Блог посты по категории с фильтром по домену и языку
  55. by_category:
  56. map: ((doc) ->
  57. if doc.type is 'blog_post' and doc.status is 'published' and doc.category_id
  58. domain = doc.domain or 'default'
  59. language = doc.language or 'ru'
  60. emit([domain, language, doc.category_id, doc.created_at], doc)
  61. ).toString()
  62. # Переводы блог постов
  63. translations:
  64. map: ((doc) ->
  65. if doc.type is 'blog_post' and doc.translation_of
  66. domain = doc.domain or 'default'
  67. language = doc.language or 'ru'
  68. emit([domain, doc.translation_of, language], doc)
  69. ).toString()
  70. # Поиск по заголовку и содержанию с фильтром по домену и языку
  71. search:
  72. map: ((doc) ->
  73. if doc.type is 'blog_post' and doc.status is 'published'
  74. domain = doc.domain or 'default'
  75. language = doc.language or 'ru'
  76. text = (doc.title + " " + doc.content + " " + doc.excerpt).toLowerCase()
  77. words = text.split(/\W+/).filter (word) -> word.length > 2
  78. for word in words
  79. emit([domain, language, word], {
  80. _id: doc._id
  81. title: doc.title
  82. excerpt: doc.excerpt
  83. created_at: doc.created_at
  84. domain: doc.domain
  85. language: doc.language
  86. })
  87. ).toString()
  88. # Design документ для мероприятий с мультидоменностью и мультиязычностью
  89. events:
  90. version: "3.0"
  91. views:
  92. # Все мероприятия по дате с фильтром по домену и языку
  93. by_date:
  94. map: ((doc) ->
  95. if doc.type is 'event'
  96. domain = doc.domain or 'default'
  97. language = doc.language or 'ru'
  98. emit([domain, language, doc.event_date], doc)
  99. ).toString()
  100. # Предстоящие мероприятия с фильтром по домену и языку
  101. upcoming:
  102. map: ((doc) ->
  103. if doc.type is 'event' and doc.status is 'upcoming'
  104. domain = doc.domain or 'default'
  105. language = doc.language or 'ru'
  106. emit([domain, language, doc.event_date], doc)
  107. ).toString()
  108. # Активные мероприятия с фильтром по домену и языку
  109. ongoing:
  110. map: ((doc) ->
  111. if doc.type is 'event' and doc.status is 'ongoing'
  112. domain = doc.domain or 'default'
  113. language = doc.language or 'ru'
  114. emit([domain, language, doc.event_date], doc)
  115. ).toString()
  116. # Мероприятия по тегам с фильтром по домену и языку
  117. by_tag:
  118. map: ((doc) ->
  119. if doc.type is 'event' and doc.tags
  120. domain = doc.domain or 'default'
  121. language = doc.language or 'ru'
  122. for tag in doc.tags
  123. emit([domain, language, tag, doc.event_date], doc)
  124. ).toString()
  125. # Мероприятия по местоположению с фильтром по домену и языку
  126. by_location:
  127. map: ((doc) ->
  128. if doc.type is 'event'
  129. domain = doc.domain or 'default'
  130. language = doc.language or 'ru'
  131. emit([domain, language, doc.location, doc.event_date], doc)
  132. ).toString()
  133. # Переводы мероприятий
  134. translations:
  135. map: ((doc) ->
  136. if doc.type is 'event' and doc.translation_of
  137. domain = doc.domain or 'default'
  138. language = doc.language or 'ru'
  139. emit([domain, doc.translation_of, language], doc)
  140. ).toString()
  141. # Design документ для слайдов с мультидоменностью и мультиязычностью
  142. slides:
  143. version: "3.0"
  144. views:
  145. # Активные слайды по порядку с фильтром по домену и языку
  146. active_ordered:
  147. map: ((doc) ->
  148. if doc.type is 'slide' and doc.active is true
  149. domain = doc.domain or 'default'
  150. language = doc.language or 'ru'
  151. emit([domain, language, doc.order], doc)
  152. ).toString()
  153. # Переводы слайдов
  154. translations:
  155. map: ((doc) ->
  156. if doc.type is 'slide' and doc.translation_of
  157. domain = doc.domain or 'default'
  158. language = doc.language or 'ru'
  159. emit([domain, doc.translation_of, language], doc)
  160. ).toString()
  161. # Design документ для товаров с мультидоменностью и мультиязычностью
  162. products:
  163. version: "3.0"
  164. views:
  165. # Все доступные товары с фильтром по домену и языку
  166. available:
  167. map: ((doc) ->
  168. if doc.type is 'product' and doc.status is 'available'
  169. domain = doc.domain or 'default'
  170. language = doc.language or 'ru'
  171. emit([domain, language, doc.created_at], doc)
  172. ).toString()
  173. # Товары по категориям с фильтром по домену и языку
  174. by_category:
  175. map: ((doc) ->
  176. if doc.type is 'product' and doc.status is 'available'
  177. domain = doc.domain or 'default'
  178. language = doc.language or 'ru'
  179. emit([domain, language, doc.category_id, doc.created_at], doc)
  180. ).toString()
  181. # Товары по тегам с фильтром по домену и языку
  182. by_tag:
  183. map: ((doc) ->
  184. if doc.type is 'product' and doc.tags
  185. domain = doc.domain or 'default'
  186. language = doc.language or 'ru'
  187. for tag in doc.tags
  188. emit([domain, language, tag, doc.created_at], doc)
  189. ).toString()
  190. # Товары по цене с фильтром по домену и языку
  191. by_price:
  192. map: ((doc) ->
  193. if doc.type is 'product' and doc.status is 'available'
  194. domain = doc.domain or 'default'
  195. language = doc.language or 'ru'
  196. emit([domain, language, doc.price], doc)
  197. ).toString()
  198. # Переводы товаров
  199. translations:
  200. map: ((doc) ->
  201. if doc.type is 'product' and doc.translation_of
  202. domain = doc.domain or 'default'
  203. language = doc.language or 'ru'
  204. emit([domain, doc.translation_of, language], doc)
  205. ).toString()
  206. # Design документ для категорий и тем с мультидоменностью и мультиязычностью
  207. categories_themes:
  208. version: "3.0"
  209. views:
  210. # Все категории по порядку с фильтром по домену и языку
  211. categories_ordered:
  212. map: ((doc) ->
  213. if doc.type is 'category'
  214. domain = doc.domain or 'default'
  215. language = doc.language or 'ru'
  216. emit([domain, language, doc.order], doc)
  217. ).toString()
  218. # Категории по родителю с фильтром по домену и языку
  219. categories_by_parent:
  220. map: ((doc) ->
  221. if doc.type is 'category'
  222. domain = doc.domain or 'default'
  223. language = doc.language or 'ru'
  224. parent = doc.parent_id or 'root'
  225. emit([domain, language, parent, doc.order], doc)
  226. ).toString()
  227. # Все темы с фильтром по домену и языку
  228. themes:
  229. map: ((doc) ->
  230. if doc.type is 'theme'
  231. domain = doc.domain or 'default'
  232. language = doc.language or 'ru'
  233. emit([domain, language, doc.name], doc)
  234. ).toString()
  235. # Переводы категорий
  236. category_translations:
  237. map: ((doc) ->
  238. if doc.type is 'category' and doc.translation_of
  239. domain = doc.domain or 'default'
  240. language = doc.language or 'ru'
  241. emit([domain, doc.translation_of, language], doc)
  242. ).toString()
  243. # Переводы тем
  244. theme_translations:
  245. map: ((doc) ->
  246. if doc.type is 'theme' and doc.translation_of
  247. domain = doc.domain or 'default'
  248. language = doc.language or 'ru'
  249. emit([domain, doc.translation_of, language], doc)
  250. ).toString()
  251. # Design документ для страниц с мультидоменностью и мультиязычностью
  252. pages:
  253. version: "3.0"
  254. views:
  255. # Все страницы по slug с фильтром по домену и языку
  256. by_slug:
  257. map: ((doc) ->
  258. if doc.type is 'page'
  259. domain = doc.domain or 'default'
  260. language = doc.language or 'ru'
  261. emit([domain, language, doc.slug], doc)
  262. ).toString()
  263. # Опубликованные страницы с фильтром по домену и языку
  264. published:
  265. map: ((doc) ->
  266. if doc.type is 'page' and doc.status is 'published'
  267. domain = doc.domain or 'default'
  268. language = doc.language or 'ru'
  269. emit([domain, language, doc.order or 0], doc)
  270. ).toString()
  271. # Страницы по родителю с фильтром по домену и языку
  272. by_parent:
  273. map: ((doc) ->
  274. if doc.type is 'page'
  275. domain = doc.domain or 'default'
  276. language = doc.language or 'ru'
  277. parent = doc.parent_id or 'root'
  278. emit([domain, language, parent, doc.order or 0], doc)
  279. ).toString()
  280. # Переводы страниц
  281. translations:
  282. map: ((doc) ->
  283. if doc.type is 'page' and doc.translation_of
  284. domain = doc.domain or 'default'
  285. language = doc.language or 'ru'
  286. emit([domain, doc.translation_of, language], doc)
  287. ).toString()
  288. # Design документ для меню с мультидоменностью и мультиязычностью
  289. menus:
  290. version: "3.0"
  291. views:
  292. # Меню по локации с фильтром по домену и языку
  293. by_location:
  294. map: ((doc) ->
  295. if doc.type is 'menu'
  296. domain = doc.domain or 'default'
  297. language = doc.language or 'ru'
  298. emit([domain, language, doc.location], doc)
  299. ).toString()
  300. # Активные меню с фильтром по домену и языку
  301. active:
  302. map: ((doc) ->
  303. if doc.type is 'menu' and doc.active is true
  304. domain = doc.domain or 'default'
  305. language = doc.language or 'ru'
  306. emit([domain, language, doc.location], doc)
  307. ).toString()
  308. # Переводы меню
  309. translations:
  310. map: ((doc) ->
  311. if doc.type is 'menu' and doc.translation_of
  312. domain = doc.domain or 'default'
  313. language = doc.language or 'ru'
  314. emit([domain, doc.translation_of, language], doc)
  315. ).toString()
  316. # Design документ для настроек с мультидоменностью и мультиязычностью
  317. settings:
  318. version: "3.0"
  319. views:
  320. # Настройки по ключу с фильтром по домену и языку
  321. by_key:
  322. map: ((doc) ->
  323. if doc.type is 'setting'
  324. domain = doc.domain or 'default'
  325. language = doc.language or 'ru'
  326. emit([domain, language, doc.key], doc)
  327. ).toString()
  328. # Глобальные настройки (без привязки к языку)
  329. global:
  330. map: ((doc) ->
  331. if doc.type is 'setting' and doc.is_global is true
  332. domain = doc.domain or 'default'
  333. emit([domain, doc.key], doc)
  334. ).toString()
  335. # Design документ для пользователей
  336. users:
  337. version: "3.0"
  338. views:
  339. # Пользователи по email
  340. by_email:
  341. map: ((doc) ->
  342. if doc.type is 'user'
  343. emit(doc.email, doc)
  344. ).toString()
  345. # Пользователи по роли
  346. by_role:
  347. map: ((doc) ->
  348. if doc.type is 'user'
  349. emit(doc.role, doc)
  350. ).toString()
  351. # Активные пользователи
  352. active:
  353. map: ((doc) ->
  354. if doc.type is 'user' and doc.active is true
  355. emit(doc.email, doc)
  356. ).toString()
  357. # Пользователи по языку предпочтения
  358. by_language:
  359. map: ((doc) ->
  360. if doc.type is 'user' and doc.preferences?.language
  361. emit(doc.preferences.language, doc)
  362. ).toString()
  363. # Design документ для заказов с мультидоменностью
  364. orders:
  365. version: "3.0"
  366. views:
  367. # Заказы по статусу с фильтром по домену
  368. by_status:
  369. map: ((doc) ->
  370. if doc.type is 'order'
  371. domain = doc.domain or 'default'
  372. emit([domain, doc.status, doc.created_at], doc)
  373. ).toString()
  374. # Заказы по пользователю с фильтром по домену
  375. by_user:
  376. map: ((doc) ->
  377. if doc.type is 'order'
  378. domain = doc.domain or 'default'
  379. emit([domain, doc.user_id, doc.created_at], doc)
  380. ).toString()
  381. # Заказы по языку
  382. by_language:
  383. map: ((doc) ->
  384. if doc.type is 'order'
  385. domain = doc.domain or 'default'
  386. language = doc.language or 'ru'
  387. emit([domain, language, doc.created_at], doc)
  388. ).toString()
  389. # Design документ для переводов контента
  390. translations:
  391. version: "3.0"
  392. views:
  393. # Все переводы по исходному документу
  394. by_source:
  395. map: ((doc) ->
  396. if doc.translation_of
  397. domain = doc.domain or 'default'
  398. emit([domain, doc.translation_of, doc.language], doc)
  399. ).toString()
  400. # Переводы по типу контента
  401. by_content_type:
  402. map: ((doc) ->
  403. if doc.translation_of
  404. domain = doc.domain or 'default'
  405. emit([domain, doc.type, doc.translation_of, doc.language], doc)
  406. ).toString()
  407. # Статусы переводов
  408. by_status:
  409. map: ((doc) ->
  410. if doc.translation_of and doc.translation_status
  411. domain = doc.domain or 'default'
  412. emit([domain, doc.translation_status, doc.language], doc)
  413. ).toString()
  414. # Design документ для глобального поиска с мультидоменностью и мультиязычностью
  415. global_search:
  416. version: "3.0"
  417. views:
  418. # Глобальный поиск по всем типам документов с фильтром по домену и языку
  419. all_content:
  420. map: ((doc) ->
  421. searchFields = {}
  422. domain = doc.domain or 'default'
  423. language = doc.language or 'ru'
  424. switch doc.type
  425. when 'blog_post'
  426. if doc.status is 'published'
  427. searchFields =
  428. title: doc.title
  429. content: doc.content
  430. excerpt: doc.excerpt
  431. author: doc.author
  432. tags: doc.tags
  433. type: 'blog_post'
  434. when 'event'
  435. searchFields =
  436. title: doc.title
  437. content: doc.content
  438. location: doc.location
  439. tags: doc.tags
  440. type: 'event'
  441. when 'product'
  442. if doc.status is 'available'
  443. searchFields =
  444. title: doc.title
  445. content: doc.content
  446. excerpt: doc.excerpt
  447. category: doc.category
  448. tags: doc.tags
  449. type: 'product'
  450. when 'category', 'theme'
  451. searchFields =
  452. name: doc.name
  453. description: doc.description
  454. type: doc.type
  455. when 'page'
  456. if doc.status is 'published'
  457. searchFields =
  458. title: doc.title
  459. content: doc.content
  460. type: 'page'
  461. # Создаем поисковый индекс
  462. if searchFields.title
  463. text = (
  464. searchFields.title + " " +
  465. (searchFields.content or "") + " " +
  466. (searchFields.excerpt or "") + " " +
  467. (searchFields.author or "") + " " +
  468. (searchFields.location or "") + " " +
  469. (searchFields.description or "")
  470. ).toLowerCase()
  471. # Добавляем теги
  472. if searchFields.tags
  473. text += " " + searchFields.tags.join(" ")
  474. words = text.split(/\W+/).filter (word) -> word.length > 2
  475. for word in words
  476. emit([domain, language, word], {
  477. _id: doc._id
  478. type: searchFields.type
  479. title: searchFields.title
  480. excerpt: searchFields.excerpt
  481. created_at: doc.created_at
  482. domain: domain
  483. language: language
  484. })
  485. ).toString()
  486. # Design документ для статистики с мультидоменностью и мультиязычностью
  487. statistics:
  488. version: "3.0"
  489. views:
  490. # Статистика по типам документов с фильтром по домену и языку
  491. by_type:
  492. map: ((doc) ->
  493. domain = doc.domain or 'default'
  494. language = doc.language or 'ru'
  495. emit([domain, language, doc.type], 1)
  496. ).toString()
  497. reduce: ((keys, values) ->
  498. sum values
  499. ).toString()
  500. # Статистика просмотров блог постов с фильтром по домену и языку
  501. blog_views:
  502. map: ((doc) ->
  503. if doc.type is 'blog_post'
  504. domain = doc.domain or 'default'
  505. language = doc.language or 'ru'
  506. emit([domain, language, doc._id], doc.views or 0)
  507. ).toString()
  508. reduce: ((keys, values) ->
  509. sum values
  510. ).toString()
  511. # Статистика мероприятий по статусу с фильтром по домену и языку
  512. events_by_status:
  513. map: ((doc) ->
  514. if doc.type is 'event'
  515. domain = doc.domain or 'default'
  516. language = doc.language or 'ru'
  517. emit([domain, language, doc.status], 1)
  518. ).toString()
  519. reduce: ((keys, values) ->
  520. sum values
  521. ).toString()
  522. # Статистика продаж товаров с фильтром по домену и языку
  523. product_sales:
  524. map: ((doc) ->
  525. if doc.type is 'order' and doc.items
  526. domain = doc.domain or 'default'
  527. language = doc.language or 'ru'
  528. for item in doc.items
  529. emit([domain, language, item.product_id], item.quantity)
  530. ).toString()
  531. reduce: ((keys, values) ->
  532. sum values
  533. ).toString()
  534. # Статистика по языкам
  535. by_language:
  536. map: ((doc) ->
  537. if doc.language
  538. domain = doc.domain or 'default'
  539. emit([domain, doc.language, doc.type], 1)
  540. ).toString()
  541. reduce: ((keys, values) ->
  542. sum values
  543. ).toString()
  544. # Design документ для ревизий и аудита
  545. audit:
  546. version: "3.0"
  547. views:
  548. # Логи изменений по дате
  549. by_date:
  550. map: ((doc) ->
  551. if doc.type is 'audit_log'
  552. emit(doc.created_at, doc)
  553. ).toString()
  554. # Логи по пользователю
  555. by_user:
  556. map: ((doc) ->
  557. if doc.type is 'audit_log'
  558. emit([doc.user_id, doc.created_at], doc)
  559. ).toString()
  560. # Логи по действию
  561. by_action:
  562. map: ((doc) ->
  563. if doc.type is 'audit_log'
  564. emit([doc.action, doc.created_at], doc)
  565. ).toString()
  566. # Логи по языку
  567. by_language:
  568. map: ((doc) ->
  569. if doc.type is 'audit_log' and doc.language
  570. emit([doc.language, doc.created_at], doc)
  571. ).toString()