| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 |
- # Design документы для CouchDB с поддержкой мультиязычных массивов и наследования
- # Версия 6.0 - унифицированная структура данных
- module.exports =
- # Design документ для универсального поиска по мультиязычному контенту
- universal_multilingual_search:
- version: "6.0"
- views:
- # Универсальный поиск по всем типам контента с поддержкой массивов
- content_search:
- map: ((doc) ->
- # Пропускаем системные документы
- if doc._id.startsWith('_design/') or doc.type in ['domain_settings', 'user', 'order', 'setting', 'audit_log']
- return
-
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- # Базовые поля для поиска
- searchFields = {}
-
- switch doc.type
- when 'blog_post', 'event', 'product', 'slide'
- if doc.status is 'published'
- searchFields =
- titles: doc.title or []
- contents: doc.content or []
- excerpts: doc.excerpt or []
- authors: doc.author or []
- tags: doc.tags or []
- type: doc.type
- languages: languages
-
- when 'category'
- searchFields =
- names: doc.name or []
- descriptions: doc.description or []
- type: 'category'
- languages: languages
-
- # Индексируем для каждого домена и языка
- if searchFields.titles
- for domain in domains
- for language, index in languages
- # Текст для поиска на конкретном языке
- searchText = (
- (searchFields.titles[index] or '') + " " +
- (searchFields.contents[index] or '') + " " +
- (searchFields.excerpts[index] or '') + " " +
- (searchFields.authors[index] or '') + " " +
- (searchFields.names?[index] or '') + " " +
- (searchFields.descriptions?[index] or '')
- ).toLowerCase()
-
- # Добавляем теги
- if searchFields.tags[index]
- searchText += " " + searchFields.tags[index].join(" ")
-
- words = searchText.split(/\W+/).filter (word) -> word.length > 2
-
- for word in words
- emit([domain, language, word], {
- _id: doc._id
- type: searchFields.type
- title: searchFields.titles[index]
- excerpt: searchFields.excerpts[index]
- language: language
- domain: domain
- created_at: doc.created_at
- })
- ).toString()
- # Поиск по конкретному типу контента
- by_content_type:
- map: ((doc) ->
- if doc.type in ['blog_post', 'event', 'product', 'slide'] and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language, index in languages
- emit([domain, doc.type, language, doc.created_at], {
- _id: doc._id
- title: doc.title?[index]
- excerpt: doc.excerpt?[index]
- image: doc.image?[index]
- author: doc.author?[index]
- language: language
- featured: doc.featured or false
- })
- ).toString()
- # Design документ для работы с мультиязычными блог постами и наследниками
- multilingual_content:
- version: "6.0"
- views:
- # Все опубликованные документы контента по доменам и языкам
- published_by_domain_language:
- map: ((doc) ->
- if doc.type in ['blog_post', 'event', 'product', 'slide'] and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language, index in languages
- contentData = {
- _id: doc._id
- type: doc.type
- title: doc.title?[index]
- excerpt: doc.excerpt?[index]
- image: doc.image?[index]
- author: doc.author?[index]
- created_at: doc.created_at
- published_at: doc.published_at
- featured: doc.featured or false
- views: doc.views or 0
- language: language
- domain: domain
- }
-
- # Добавляем специфичные поля для наследников
- switch doc.type
- when 'event'
- contentData.event_date = doc.event_data?.event_date
- contentData.location = doc.event_data?.location?[index]
- contentData.price = doc.event_data?.price?[index]
- contentData.status = doc.event_data?.status
-
- when 'product'
- contentData.price = doc.product_data?.price?[index]
- contentData.status = doc.product_data?.status
- contentData.inventory = doc.product_data?.inventory
-
- when 'slide'
- contentData.order = doc.slide_data?.order
- contentData.active = doc.slide_data?.active
-
- emit([domain, language, doc.created_at], contentData)
- ).toString()
- # Избранный контент с приоритетом
- featured_content:
- map: ((doc) ->
- if doc.type in ['blog_post', 'event', 'product', 'slide'] and doc.status is 'published' and doc.featured is true
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language, index in languages
- emit([domain, language, doc.featured, doc.created_at], {
- _id: doc._id
- type: doc.type
- title: doc.title?[index]
- excerpt: doc.excerpt?[index]
- image: doc.image?[index]
- language: language
- })
- ).toString()
- # Контент по категориям с поддержкой иерархии
- by_category_path:
- map: ((doc) ->
- if doc.type in ['blog_post', 'event', 'product', 'slide'] and doc.status is 'published' and doc.category_path
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language, index in languages
- # Эмитим для каждой категории в пути
- for category_id in doc.category_path
- emit([domain, language, category_id, doc.created_at], {
- _id: doc._id
- type: doc.type
- title: doc.title?[index]
- category_id: doc.category_id
- language: language
- })
- ).toString()
- # Design документ для событий (events) с мультиязычными данными
- events_multilingual:
- version: "6.0"
- views:
- # События по дате с мультиязычной информацией
- by_date_multilingual:
- map: ((doc) ->
- if doc.type is 'event' and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- event_date = doc.event_data?.event_date
-
- if event_date
- for domain in domains
- for language, index in languages
- emit([domain, language, event_date], {
- _id: doc._id
- title: doc.title?[index]
- excerpt: doc.excerpt?[index]
- location: doc.event_data?.location?[index]
- price: doc.event_data?.price?[index]
- available_tickets: doc.event_data?.available_tickets
- status: doc.event_data?.status
- image: doc.image?[index]
- language: language
- })
- ).toString()
- # Предстоящие события
- upcoming_events:
- map: ((doc) ->
- if doc.type is 'event' and doc.event_data?.status is 'upcoming'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- event_date = doc.event_data?.event_date
-
- if event_date
- for domain in domains
- for language, index in languages
- emit([domain, language, event_date], {
- _id: doc._id
- title: doc.title?[index]
- location: doc.event_data?.location?[index]
- price: doc.event_data?.price?[index]
- available_tickets: doc.event_data?.available_tickets
- image: doc.image?[index]
- language: language
- })
- ).toString()
- # События по местоположению
- by_location_multilingual:
- map: ((doc) ->
- if doc.type is 'event' and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- locations = doc.event_data?.location or []
-
- for domain in domains
- for language, index in languages
- location = locations[index]
- if location
- emit([domain, language, location, doc.event_data?.event_date], {
- _id: doc._id
- title: doc.title?[index]
- event_date: doc.event_data?.event_date
- price: doc.event_data?.price?[index]
- language: language
- })
- ).toString()
- # Design документ для товаров (products) с мультиязычными данными
- products_multilingual:
- version: "6.0"
- views:
- # Товары по статусу и доступности
- by_status_multilingual:
- map: ((doc) ->
- if doc.type is 'product' and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- product_status = doc.product_data?.status
-
- for domain in domains
- for language, index in languages
- emit([domain, language, product_status, doc.created_at], {
- _id: doc._id
- title: doc.title?[index]
- price: doc.product_data?.price?[index]
- compare_price: doc.product_data?.compare_price?[index]
- inventory: doc.product_data?.inventory
- sku: doc.product_data?.sku
- image: doc.image?[index]
- language: language
- })
- ).toString()
- # Товары по цене
- by_price_range:
- map: ((doc) ->
- if doc.type is 'product' and doc.status is 'published' and doc.product_data?.status is 'available'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- prices = doc.product_data?.price or []
-
- for domain in domains
- for language, index in languages
- price = prices[index]
- if price
- # Группируем по ценовым диапазонам
- price_range = Math.floor(price / 100) * 100
- emit([domain, language, price_range, doc.created_at], {
- _id: doc._id
- title: doc.title?[index]
- price: price
- inventory: doc.product_data?.inventory
- image: doc.image?[index]
- language: language
- })
- ).toString()
- # Товары по тегам
- by_tags_multilingual:
- map: ((doc) ->
- if doc.type is 'product' and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- tagsArrays = doc.tags or []
-
- for domain in domains
- for language, index in languages
- tags = tagsArrays[index] or []
- for tag in tags
- emit([domain, language, tag, doc.created_at], {
- _id: doc._id
- title: doc.title?[index]
- price: doc.product_data?.price?[index]
- image: doc.image?[index]
- language: language
- })
- ).toString()
- # Design документ для слайдеров (slides) с мультиязычными данными
- slides_multilingual:
- version: "6.0"
- views:
- # Активные слайды по порядку
- active_ordered_multilingual:
- map: ((doc) ->
- if doc.type is 'slide' and doc.slide_data?.active is true
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- order = doc.slide_data?.order or 0
-
- for domain in domains
- for language, index in languages
- emit([domain, language, order], {
- _id: doc._id
- title: doc.title?[index]
- content: doc.content?[index]
- image: doc.image?[index]
- button_text: doc.slide_data?.button_text?[index]
- button_link: doc.slide_data?.button_link?[index]
- language: language
- })
- ).toString()
- # Слайды по датам активности
- by_active_dates:
- map: ((doc) ->
- if doc.type is 'slide' and doc.slide_data?.active is true
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- start_date = doc.slide_data?.start_date
- end_date = doc.slide_data?.end_date
-
- if start_date and end_date
- for domain in domains
- emit([domain, start_date, end_date], {
- _id: doc._id
- title: doc.title?[0] # Берем первый язык для ключа
- order: doc.slide_data?.order
- })
- ).toString()
- # Design документ для иерархических категорий с мультиязычностью
- categories_hierarchical_multilingual:
- version: "6.0"
- views:
- # Категории по уровню иерархии
- by_level_multilingual:
- map: ((doc) ->
- if doc.type is 'category'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- level = doc.level or 0
-
- for domain in domains
- for language, index in languages
- emit([domain, language, level, doc.order], {
- _id: doc._id
- name: doc.name?[index]
- slug: doc.slug?[index]
- description: doc.description?[index]
- parent_id: doc.parent_id
- level: level
- order: doc.order
- active: doc.active
- featured: doc.featured
- show_in_menu: doc.show_in_menu
- language: language
- })
- ).toString()
- # Категории по родителю для построения дерева
- by_parent_multilingual:
- map: ((doc) ->
- if doc.type is 'category'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- parent_id = doc.parent_id or 'root'
-
- for domain in domains
- for language, index in languages
- emit([domain, language, parent_id, doc.order], {
- _id: doc._id
- name: doc.name?[index]
- slug: doc.slug?[index]
- level: doc.level
- children_count: doc.children_count
- order: doc.order
- active: doc.active
- language: language
- })
- ).toString()
- # Корневые категории
- root_categories_multilingual:
- map: ((doc) ->
- if doc.type is 'category' and (not doc.parent_id or doc.parent_id is null)
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language, index in languages
- emit([domain, language, doc.order], {
- _id: doc._id
- name: doc.name?[index]
- slug: doc.slug?[index]
- level: 0
- children_count: doc.children_count
- order: doc.order
- active: doc.active
- featured: doc.featured
- language: language
- })
- ).toString()
- # Design документ для статистики и аналитики мультиязычного контента
- multilingual_statistics:
- version: "6.0"
- views:
- # Статистика по типам контента и языкам
- content_stats_by_language:
- map: ((doc) ->
- if doc.type in ['blog_post', 'event', 'product', 'slide'] and doc.status is 'published'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language in languages
- # Статистика по типам
- emit([domain, 'type_count', doc.type, language], 1)
-
- # Статистика по датам
- if doc.created_at
- date = doc.created_at.split('T')[0]
- emit([domain, 'creation_date', date, language], 1)
-
- # Статистика просмотров
- if doc.views
- emit([domain, 'views', doc.type, language], doc.views)
- ).toString()
- reduce: ((keys, values) ->
- sum values
- ).toString()
- # Статистика популярности контента
- content_popularity_multilingual:
- map: ((doc) ->
- if doc.type is 'blog_post'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- views = doc.views or 0
- likes = doc.likes or 0
- shares = doc.shares or 0
-
- popularity = views + (likes * 2) + (shares * 3)
-
- for domain in domains
- for language in languages
- emit([domain, language, popularity], {
- _id: doc._id
- type: doc.type
- title: doc.title?[0] # Первый язык для ключа
- views: views
- likes: likes
- shares: shares
- popularity: popularity
- })
-
- else if doc.type is 'event'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- tickets_sold = (doc.event_data?.total_tickets or 0) - (doc.event_data?.available_tickets or 0)
-
- for domain in domains
- for language in languages
- emit([domain, language, tickets_sold], {
- _id: doc._id
- type: doc.type
- title: doc.title?[0]
- tickets_sold: tickets_sold
- total_tickets: doc.event_data?.total_tickets
- })
- ).toString()
- # Design документ для работы с заказами
- orders_management:
- version: "6.0"
- views:
- # Заказы по статусу и домену
- by_status_and_domain:
- map: ((doc) ->
- if doc.type is 'order'
- domain = doc.domain or 'default'
- languages = doc.language or ['ru']
-
- for language in languages
- emit([domain, language, doc.status, doc.created_at], {
- _id: doc._id
- total: doc.total
- currency: doc.currency
- customer_name: doc.customer_info?.name?[0] # Первый язык
- created_at: doc.created_at
- items_count: doc.items?.length or 0
- })
- ).toString()
- # Статистика продаж по доменам и языкам
- sales_statistics_multilingual:
- map: ((doc) ->
- if doc.type is 'order' and doc.status is 'completed'
- domain = doc.domain or 'default'
- languages = doc.language or ['ru']
- date = doc.created_at.split('T')[0]
-
- for language in languages
- # Общая сумма за день
- emit([domain, language, 'daily_sales', date], doc.total)
-
- # Количество заказов за день
- emit([domain, language, 'daily_orders', date], 1)
-
- # Статистика по товарам
- if doc.items
- for item in doc.items
- emit([domain, language, 'product_sales', item.product_id], item.quantity)
- emit([domain, language, 'product_revenue', item.product_id], item.total)
- ).toString()
- reduce: ((keys, values) ->
- sum values
- ).toString()
- # Design документ для пользователей и управления доступом
- users_management:
- version: "6.0"
- views:
- # Пользователи по email и роли
- by_email_and_role:
- map: ((doc) ->
- if doc.type is 'user'
- emit([doc.email, doc.role], {
- _id: doc._id
- name: doc.name?[0] # Первый язык
- active: doc.active
- last_login: doc.last_login
- domains_access: doc.domains_access
- })
- ).toString()
- # Активные пользователи по доменам
- active_users_by_domain:
- map: ((doc) ->
- if doc.type is 'user' and doc.active is true
- domains = doc.domains_access or []
- for domain in domains
- emit([domain, doc.role, doc.email], {
- _id: doc._id
- name: doc.name?[0]
- email: doc.email
- last_login: doc.last_login
- })
- ).toString()
- # Design документ для системы уведомлений с мультиязычностью
- multilingual_notifications:
- version: "6.0"
- views:
- # Уведомления о предстоящих событиях
- event_reminders_multilingual:
- map: ((doc) ->
- if doc.type is 'event' and doc.event_data?.status is 'upcoming'
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
- event_date = new Date(doc.event_data.event_date)
- now = new Date()
-
- # Уведомление за 7 дней до события
- sevenDaysBefore = new Date(event_date.getTime() - 7 * 24 * 60 * 60 * 1000)
- if now >= sevenDaysBefore and now < event_date
- for domain in domains
- for language, index in languages
- emit([domain, language, 'event_reminder_7d', doc.event_data.event_date], {
- _id: doc._id
- title: doc.title?[index]
- event_date: doc.event_data.event_date
- domain: domain
- language: language
- notification_type: 'event_reminder_7d'
- })
-
- # Уведомление за 1 день до события
- oneDayBefore = new Date(event_date.getTime() - 24 * 60 * 60 * 1000)
- if now >= oneDayBefore and now < event_date
- for domain in domains
- for language, index in languages
- emit([domain, language, 'event_reminder_1d', doc.event_data.event_date], {
- _id: doc._id
- title: doc.title?[index]
- event_date: doc.event_data.event_date
- domain: domain
- language: language
- notification_type: 'event_reminder_1d'
- })
- ).toString()
- # Уведомления о низком количестве товаров
- low_inventory_alerts:
- map: ((doc) ->
- if doc.type is 'product' and doc.product_data?.inventory < 10
- domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default']
- languages = doc.language or ['ru']
-
- for domain in domains
- for language, index in languages
- emit([domain, language, 'low_inventory', doc.product_data.inventory], {
- _id: doc._id
- title: doc.title?[index]
- inventory: doc.product_data.inventory
- sku: doc.product_data.sku
- domain: domain
- language: language
- notification_type: 'low_inventory'
- })
- ).toString()
|