# Design документы для CouchDB с поддержкой иерархических категорий # Версия 5.0 - с иерархической структурой категорий module.exports = # Design документ для работы с иерархическими категориями categories_hierarchical: version: "5.0" views: # Все категории по уровню иерархии by_level: map: ((doc) -> if doc.type is 'category' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] level = doc.level or 0 for domain in domains emit([domain, level, doc.order], { _id: doc._id name: doc.name slug: doc.slug parent_id: doc.parent_id level: level order: doc.order active: doc.active featured: doc.featured show_in_menu: doc.show_in_menu }) ).toString() # Категории по родителю (для построения дерева) by_parent: map: ((doc) -> if doc.type is 'category' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] parent_id = doc.parent_id or 'root' for domain in domains emit([domain, parent_id, doc.order], { _id: doc._id name: doc.name slug: doc.slug level: doc.level children_count: doc.children_count order: doc.order active: doc.active }) ).toString() # Полное дерево категорий с путями by_path: map: ((doc) -> if doc.type is 'category' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] parent_path = doc.parent_path or [] for domain in domains # Эмитим каждый сегмент пути для быстрого поиска for path_segment, index in parent_path emit([domain, path_segment, doc.level, doc.order], doc) # Эмитим саму категорию emit([domain, doc._id, doc.level, doc.order], doc) ).toString() # Корневые категории root_categories: 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'] for domain in domains emit([domain, doc.order], { _id: doc._id name: doc.name slug: doc.slug level: 0 children_count: doc.children_count order: doc.order active: doc.active featured: doc.featured }) ).toString() # Категории для меню menu_categories: map: ((doc) -> if doc.type is 'category' and doc.show_in_menu is true domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] level = doc.level or 0 for domain in domains emit([domain, level, doc.menu_order or doc.order], { _id: doc._id name: doc.name slug: doc.slug parent_id: doc.parent_id level: level menu_order: doc.menu_order icon: doc.icon color: doc.color }) ).toString() # Design документ для контента с иерархическими категориями content_with_hierarchical_categories: version: "5.0" views: # Контент по полному пути категории by_category_path: map: ((doc) -> if (doc.type is 'blog_post' or doc.type is 'event') and doc.category_path domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains # Эмитим для каждого сегмента пути категории for category_id in doc.category_path emit([domain, category_id, doc.created_at], { _id: doc._id type: doc.type title: doc.title category_id: doc.category_id category_path: doc.category_path created_at: doc.created_at status: doc.status featured: doc.featured }) ).toString() # Контент по конечной категории (самой глубокой) by_leaf_category: map: ((doc) -> if (doc.type is 'blog_post' or doc.type is 'event') and doc.category_path domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] leaf_category = doc.category_path[doc.category_path.length - 1] for domain in domains emit([domain, leaf_category, doc.created_at], { _id: doc._id type: doc.type title: doc.title category_id: doc.category_id created_at: doc.created_at status: doc.status }) ).toString() # Контент по корневой категории by_root_category: map: ((doc) -> if (doc.type is 'blog_post' or doc.type is 'event') and doc.category_path domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] root_category = doc.category_path[0] for domain in domains emit([domain, root_category, doc.created_at], { _id: doc._id type: doc.type title: doc.title root_category: root_category created_at: doc.created_at status: doc.status }) ).toString() # Design документ для поиска с учетом иерархии категорий search_with_category_hierarchy: version: "5.0" views: # Поиск по контенту с информацией о категории content_with_category_info: map: ((doc) -> if (doc.type is 'blog_post' and doc.status is 'published') or doc.type is 'event' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] search_text = (doc.title + " " + (doc.content or "") + " " + (doc.excerpt or "")).toLowerCase() words = search_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: doc.title excerpt: doc.excerpt category_id: doc.category_id category_path: doc.category_path created_at: doc.created_at domain: domain }) ).toString() # Поиск по категориям и тегам by_category_and_tags: map: ((doc) -> if (doc.type is 'blog_post' and doc.status is 'published') or doc.type is 'event' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains # По категории if doc.category_id emit([domain, 'category', doc.category_id, doc.created_at], { _id: doc._id type: doc.type title: doc.title }) # По тегам if doc.tags for tag in doc.tags emit([domain, 'tag', tag, doc.created_at], { _id: doc._id type: doc.type title: doc.title }) ).toString() # Design документ для статистики иерархических категорий category_statistics: version: "5.0" views: # Статистика контента по категориям content_count_by_category: map: ((doc) -> if (doc.type is 'blog_post' or doc.type is 'event') and doc.category_id domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains # По конечной категории emit([domain, 'leaf_category', doc.category_id, doc.type], 1) # По всем категориям в пути if doc.category_path for category_id in doc.category_path emit([domain, 'path_category', category_id, doc.type], 1) ).toString() reduce: ((keys, values) -> sum values ).toString() # Статистика популярности категорий category_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 for domain in domains if doc.category_id emit([domain, doc.category_id], views) if doc.category_path for category_id in doc.category_path emit([domain, category_id], views) else 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 if doc.category_id emit([domain, doc.category_id], tickets_sold) ).toString() reduce: ((keys, values) -> sum values ).toString() # Design документ для навигации по иерархии category_navigation: version: "5.0" views: # Соседние категории (одного уровня) siblings_categories: map: ((doc) -> if doc.type is 'category' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] parent_id = doc.parent_id or 'root' for domain in domains emit([domain, parent_id, doc.order], { _id: doc._id name: doc.name slug: doc.slug order: doc.order level: doc.level }) ).toString() # Дочерние категории children_categories: map: ((doc) -> if doc.type is 'category' domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains emit([domain, doc._id, 'children'], { _id: doc._id name: doc.name children_count: doc.children_count has_children: doc.children_count > 0 }) ).toString() # Хлебные крошки для категорий breadcrumbs: map: ((doc) -> if doc.type is 'category' and doc.parent_path domains = if Array.isArray(doc.domain) then doc.domain else [doc.domain or 'default'] for domain in domains # Эмитим для каждого родителя в пути for parent_id, index in doc.parent_path emit([domain, doc._id, 'parent', index], { parent_id: parent_id position: index current_category: doc._id }) ).toString() # Design документ для мультидоменного поиска (обновленный) multi_domain_search: version: "5.0" views: # Универсальный поиск с учетом иерархии категорий universal_search_with_categories: 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 category_path: doc.category_path type: 'blog_post' when 'event' searchFields = title: doc.title content: doc.content location: doc.location tags: doc.tags category_path: doc.category_path type: 'event' if searchFields.title text = ( searchFields.title + " " + (searchFields.content or "") + " " + (searchFields.excerpt or "") + " " + (searchFields.author or "") + " " + (searchFields.location 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 category_path: searchFields.category_path created_at: doc.created_at domain: domain language: language }) ).toString() # Design документ для блог постов (обновленный) blog_posts: version: "5.0" views: # Блог посты с информацией о категориях published_with_categories: 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 category_id: doc.category_id category_path: doc.category_path created_at: doc.created_at domain: domain language: language featured: doc.featured or false views: doc.views or 0 }) ).toString() # Design документ для мероприятий (обновленный) events: version: "5.0" views: # Мероприятия с информацией о категориях by_date_with_categories: 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 category_id: doc.category_id category_path: doc.category_path domain: domain language: language available_tickets: doc.available_tickets }) ).toString()