Реализация переноса комментариев и отзывов при миграции сайта

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация переноса комментариев и отзывов при миграции сайта
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация переноса комментариев и отзывов при миграции сайта

Комментарии и отзывы — пользовательский контент с историей и связями. При переносе важно сохранить дерево ответов, авторство, даты и статусы модерации.

Структура данных комментариев

Стандартная структура (WordPress как пример):

-- wp_comments
comment_ID, comment_post_ID, comment_author, comment_author_email,
comment_author_url, comment_date, comment_content, comment_approved,
comment_parent (для ответов), user_id (если зарегистрированный)

Отличия для отзывов (WooCommerce):

-- Отзыв = комментарий с type='review'
-- Рейтинг хранится в wp_commentmeta: key='rating', value=1-5

Экспорт из WordPress

def export_comments(wp_db):
    cursor = wp_db.cursor(dictionary=True)
    cursor.execute("""
        SELECT
            c.comment_ID as id,
            c.comment_post_ID as post_legacy_id,
            c.comment_author as author_name,
            c.comment_author_email as author_email,
            c.comment_date_gmt as created_at,
            c.comment_content as content,
            c.comment_approved as status,
            c.comment_parent as parent_id,
            c.user_id as wp_user_id,
            c.comment_type as type,
            cm.meta_value as rating
        FROM wp_comments c
        LEFT JOIN wp_commentmeta cm ON c.comment_ID = cm.comment_id
            AND cm.meta_key = 'rating'
        WHERE c.comment_type IN ('comment', 'review', '')
        ORDER BY c.comment_parent ASC, c.comment_ID ASC
    """)
    return cursor.fetchall()

Важно: ORDER BY comment_parent ASC — родительские комментарии обрабатываются раньше дочерних.

Перенос с сохранением дерева ответов

def migrate_comments(wp_db, new_db, post_id_map, user_id_map):
    comments = export_comments(wp_db)

    # Маппинг старых comment_ID → новых
    comment_id_map = {}

    for comment in comments:
        # Найти новый post ID
        new_post_id = post_id_map.get(comment['post_legacy_id'])
        if not new_post_id:
            continue  # пост не перенесён — пропустить

        # Найти новый parent ID
        new_parent_id = None
        if comment['parent_id']:
            new_parent_id = comment_id_map.get(comment['parent_id'])
            if not new_parent_id:
                print(f"Parent comment {comment['parent_id']} not found, skipping child")
                continue

        # Определить статус
        status_map = {'1': 'approved', '0': 'pending', 'spam': 'spam', 'trash': 'deleted'}
        status = status_map.get(str(comment['status']), 'pending')

        new_comment = {
            'post_id': new_post_id,
            'author_name': comment['author_name'],
            'author_email': comment['author_email'],
            'content': comment['content'],
            'status': status,
            'parent_id': new_parent_id,
            'user_id': user_id_map.get(comment['wp_user_id']),
            'created_at': comment['created_at'],
            'rating': int(comment['rating']) if comment['rating'] else None,
            'legacy_id': comment['id'],
        }

        new_id = new_db.create_comment(new_comment)
        comment_id_map[comment['id']] = new_id

    print(f"Migrated {len(comment_id_map)} comments")
    return comment_id_map

Отзывы с Disqus

def export_disqus_comments(disqus_api_key, forum_shortname):
    """Экспорт комментариев из Disqus через API"""
    import requests

    all_posts = []
    cursor = None

    while True:
        params = {
            'api_key': disqus_api_key,
            'forum': forum_shortname,
            'limit': 100,
        }
        if cursor:
            params['cursor'] = cursor

        resp = requests.get('https://disqus.com/api/3.0/posts/list.json', params=params)
        data = resp.json()

        all_posts.extend(data['response'])

        if not data['cursor']['hasNext']:
            break
        cursor = data['cursor']['next']

    return all_posts

Disqus также предоставляет XML-экспорт через admin-панель (Settings → Export). Формат WXEP совместим с WordPress XML-импортом.

Перенос рейтингов/отзывов (e-commerce)

def migrate_product_reviews(wp_db, new_db, product_id_map, user_id_map):
    cursor = wp_db.cursor(dictionary=True)
    cursor.execute("""
        SELECT
            c.comment_ID, c.comment_post_ID, c.comment_author,
            c.comment_author_email, c.comment_content, c.comment_date_gmt,
            c.comment_approved,
            MAX(CASE WHEN cm.meta_key = 'rating' THEN cm.meta_value END) as rating,
            MAX(CASE WHEN cm.meta_key = 'verified' THEN cm.meta_value END) as verified
        FROM wp_comments c
        JOIN wp_commentmeta cm ON c.comment_ID = cm.comment_id
        WHERE c.comment_type = 'review'
        GROUP BY c.comment_ID
    """)

    for review in cursor.fetchall():
        new_product_id = product_id_map.get(review['comment_post_ID'])
        if not new_product_id:
            continue

        new_db.create_review({
            'product_id': new_product_id,
            'author_name': review['comment_author'],
            'author_email': review['comment_author_email'],
            'content': review['comment_content'],
            'rating': int(review['rating'] or 5),
            'is_verified': review['verified'] == '1',
            'status': 'approved' if review['comment_approved'] == '1' else 'pending',
            'created_at': review['comment_date_gmt'],
        })

Верификация после переноса

def verify_comments_migration(wp_db, new_db, post_id_map):
    cursor = wp_db.cursor()
    cursor.execute("""
        SELECT comment_post_ID, COUNT(*) as count
        FROM wp_comments
        WHERE comment_approved = '1'
        GROUP BY comment_post_ID
    """)
    wp_counts = dict(cursor.fetchall())

    mismatches = []
    for wp_post_id, expected_count in wp_counts.items():
        new_post_id = post_id_map.get(wp_post_id)
        if not new_post_id:
            continue
        actual_count = new_db.count_comments(new_post_id)
        if actual_count != expected_count:
            mismatches.append((wp_post_id, expected_count, actual_count))

    if mismatches:
        print("Comment count mismatches:")
        for wp_id, expected, actual in mismatches:
            print(f"  Post {wp_id}: expected {expected}, got {actual}")
    return len(mismatches) == 0

Срок выполнения

Перенос комментариев с сохранением дерева ответов, авторства и рейтингов — 2–3 рабочих дня.