# Design документы для CouchDB с поддержкой мультидоменности и мультиязычности # Версия 4.0 - с учетом последних изменений в правилах module.exports = # Design документ для мультидоменного поиска multi_domain_search: version: "4.0" views: # Универсальный поиск по всем доменам и языкам universal_search: map: ((doc) -> # Пропускаем системные документы if doc._id.startsWith('_design/') or doc.type is 'domain_settings' return domain = doc.domain or 'default' domains = if Array.isArray(domain) then domain else [domain] language = doc.language or 'ru' searchFields = {} searchText = "" # Определяем поля для поиска в зависимости от типа документа switch doc.type when 'blog_post' if doc.status is 'published' searchFields = title: doc.title content: doc.content excerpt: doc.excerpt author: doc.author tags: doc.tags type: 'blog_post' domain: domains language: language when 'event' searchFields = title: doc.title content: doc.content location: doc.location tags: doc.tags type: 'event' domain: domains language: language when 'product' if doc.status is 'available' searchFields = title: doc.title content: doc.content excerpt: doc.excerpt category: doc.category tags: doc.tags type: 'product' domain: domains language: language when 'category', 'theme' searchFields = name: doc.name description: doc.description type: doc.type domain: domains language: language when 'page' if doc.status is 'published' searchFields = title: doc.title content: doc.content type: 'page' domain: domains language: language # Создаем поисковый индекс для каждого домена if searchFields.title text = ( searchFields.title + " " + (searchFields.content or "") + " " + (searchFields.excerpt or "") + " " + (searchFields.author or "") + " " + (searchFields.location or "") + " " + (searchFields.description or "") ).toLowerCase() if searchFields.tags text += " " + searchFields.tags.join(" ") words = text.split(/\W+/).filter (word) -> word.length > 2 for domain in domains for word in words emit([domain, language, word], { _id: doc._id type: searchFields.type title: searchFields.title excerpt: searchFields.excerpt created_at: doc.created_at domain: domain language: language relevance: 1 }) ).toString() # Поиск по конкретному домену domain_specific_search: map: ((doc) -> if doc._id.startsWith('_design/') or doc.type is 'domain_settings' return domain = doc.domain or 'default' domains = if Array.isArray(domain) then domain else [domain] language = doc.language or 'ru' searchFields = {} switch doc.type when 'blog_post' if doc.status is 'published' searchFields = {title: doc.title, content: doc.content, excerpt: doc.excerpt} when 'event' searchFields = {title: doc.title, content: doc.content, location: doc.location} when 'product' if doc.status is 'available' searchFields = {title: doc.title, content: doc.content, excerpt: doc.excerpt} when 'page' if doc.status is 'published' searchFields = {title: doc.title, content: doc.content} if searchFields.title text = (searchFields.title + " " + (searchFields.content or "") + " " + (searchFields.excerpt or "")).toLowerCase() words = text.split(/\W+/).filter (word) -> word.length > 2 for domain in domains for word in words emit([domain, word], { _id: doc._id type: doc.type title: searchFields.title language: language domain: domain }) ).toString() # Design документ для блог постов с улучшенной мультидоменностью blog_posts: version: "4.0" views: # Все опубликованные блог посты с поддержкой массива доменов published_multidomain: map: ((doc) -> if doc.type is 'blog_post' and doc.status is 'published' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' for domain in domains emit([domain, language, doc.created_at], { _id: doc._id title: doc.title excerpt: doc.excerpt image: doc.image author: doc.author created_at: doc.created_at domain: domain language: language featured: doc.featured or false views: doc.views or 0 }) ).toString() # Блог посты по тегам с мультидоменностью by_tag_multidomain: map: ((doc) -> if doc.type is 'blog_post' and doc.status is 'published' and doc.tags domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' for domain in domains for tag in doc.tags emit([domain, language, tag, doc.created_at], doc) ).toString() # Избранные посты с приоритетом доменов featured_multidomain: map: ((doc) -> if doc.type is 'blog_post' and doc.status is 'published' and doc.featured is true domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' domainPriority = doc.domain_priority or domains for domain, index in domains priority = domainPriority.indexOf(domain) priority = if priority is -1 then 999 else priority emit([domain, priority, doc.created_at], doc) ).toString() # Переводы блог постов translations_advanced: map: ((doc) -> if doc.type is 'blog_post' and doc.translation_of domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' for domain in domains emit([domain, doc.translation_of, language], { _id: doc._id title: doc.title language: doc.language translation_status: doc.translation_status domain: domain }) ).toString() # Design документ для мероприятий с расширенной мультидоменностью events: version: "4.0" views: # Мероприятия по дате с поддержкой массива доменов by_date_multidomain: map: ((doc) -> if doc.type is 'event' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' for domain in domains emit([domain, language, doc.event_date], { _id: doc._id title: doc.title event_date: doc.event_date location: doc.location price: doc.price status: doc.status image: doc.image domain: domain language: language available_tickets: doc.available_tickets }) ).toString() # Предстоящие мероприятия с приоритетом доменов upcoming_priority: map: ((doc) -> if doc.type is 'event' and doc.status is 'upcoming' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' domainPriority = doc.domain_priority or domains for domain, index in domains priority = domainPriority.indexOf(domain) priority = if priority is -1 then 999 else priority emit([domain, priority, doc.event_date], doc) ).toString() # Мероприятия по местоположению с мультидоменностью by_location_advanced: map: ((doc) -> if doc.type is 'event' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] language = doc.language or 'ru' for domain in domains locationKey = doc.location?.toLowerCase().replace(/\s+/g, '_') or 'unknown' emit([domain, language, locationKey, doc.event_date], doc) ).toString() # Design документ для статистики и аналитики statistics_advanced: version: "4.0" views: # Статистика по доменам и типам контента domain_content_stats: map: ((doc) -> if doc._id.startsWith('_design/') return domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] docType = doc.type or 'unknown' language = doc.language or 'ru' for domain in domains # Статистика по типам документов emit([domain, 'type_count', docType], 1) # Статистика по языкам emit([domain, 'language_count', language], 1) # Статистика по датам создания if doc.created_at date = doc.created_at.split('T')[0] # YYYY-MM-DD emit([domain, 'creation_date', date], 1) # Статистика просмотров для блог постов if doc.type is 'blog_post' and doc.views emit([domain, 'blog_views', doc._id], doc.views) # Статистика доступных билетов для мероприятий if doc.type is 'event' and doc.available_tickets emit([domain, 'available_tickets', doc._id], doc.available_tickets) ).toString() reduce: ((keys, values) -> sum values ).toString() # Аналитика популярности контента content_popularity: map: ((doc) -> if doc.type is 'blog_post' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] 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 emit([domain, popularity], { _id: doc._id title: doc.title views: views likes: likes shares: shares popularity: popularity created_at: doc.created_at }) if doc.type is 'event' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] tickets_sold = (doc.total_tickets or 0) - (doc.available_tickets or 0) for domain in domains emit([domain, tickets_sold], { _id: doc._id title: doc.title tickets_sold: tickets_sold total_tickets: doc.total_tickets event_date: doc.event_date }) ).toString() # Design документ для управления переводами translation_management: version: "4.0" views: # Все переводы по исходному документу и домену by_source_and_domain: map: ((doc) -> if doc.translation_of domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains emit([domain, doc.translation_of, doc.language], { _id: doc._id type: doc.type title: doc.title language: doc.language translation_status: doc.translation_status domain: domain created_at: doc.created_at }) ).toString() # Статусы переводов по доменам translation_status_by_domain: map: ((doc) -> if doc.translation_of and doc.translation_status domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains emit([domain, doc.translation_status, doc.language], { _id: doc._id translation_of: doc.translation_of type: doc.type title: doc.title }) ).toString() # Отсутствующие переводы missing_translations: map: ((doc) -> if doc.type and doc.language and not doc.translation_of domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] supportedLanguages = ['ru', 'en', 'tj'] for domain in domains for targetLang in supportedLanguages if targetLang != doc.language emit([domain, doc._id, targetLang], { original_id: doc._id original_language: doc.language target_language: targetLang domain: domain type: doc.type title: doc.title }) ).toString() # Design документ для работы с заказами orders_management: version: "4.0" views: # Заказы по статусу и домену by_status_and_domain: map: ((doc) -> if doc.type is 'order' domain = doc.domain or 'default' emit([domain, doc.status, doc.created_at], { _id: doc._id total: doc.total currency: doc.currency customer_name: doc.customer_info?.name created_at: doc.created_at items_count: doc.items?.length or 0 }) ).toString() # Статистика продаж по доменам sales_statistics: map: ((doc) -> if doc.type is 'order' and doc.status is 'completed' domain = doc.domain or 'default' date = doc.created_at.split('T')[0] # YYYY-MM-DD # Общая сумма за день emit([domain, 'daily_sales', date], doc.total) # Количество заказов за день emit([domain, 'daily_orders', date], 1) # Статистика по товарам if doc.items for item in doc.items emit([domain, 'product_sales', item.product_id], item.quantity) emit([domain, 'product_revenue', item.product_id], item.total) ).toString() reduce: ((keys, values) -> sum values ).toString() # Design документ для системы уведомлений notifications: version: "4.0" views: # События для уведомлений по доменам domain_events: map: ((doc) -> if doc.type is 'event' and doc.status is 'upcoming' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] eventDate = new Date(doc.event_date) now = new Date() # Уведомление за 7 дней до события sevenDaysBefore = new Date(eventDate.getTime() - 7 * 24 * 60 * 60 * 1000) if now >= sevenDaysBefore and now < eventDate for domain in domains emit([domain, 'event_reminder_7d', doc.event_date], { _id: doc._id title: doc.title event_date: doc.event_date domain: domain notification_type: 'event_reminder_7d' }) # Уведомление за 1 день до события oneDayBefore = new Date(eventDate.getTime() - 24 * 60 * 60 * 1000) if now >= oneDayBefore and now < eventDate for domain in domains emit([domain, 'event_reminder_1d', doc.event_date], { _id: doc._id title: doc.title event_date: doc.event_date domain: domain notification_type: 'event_reminder_1d' }) ).toString()