Статьи

Использование Neo4j для интерпретации CSV-файлов для компенсации продаж в WoW

Планирование компенсаций и расчеты в сложных сбытовых организациях могут быть чрезвычайно сложными для традиционных баз данных. Достаточно крупные организации часто заканчивают пакетирование этих процессов в одночасье или еженедельной работой.

Для целей этого поста в блоге давайте взглянем на Slashco — самую горячую многоуровневую маркетинговую «гильдию» в World of Warcraft. Получите полные наборы данных и запросы Cypher, использованные в этой записи блога здесь .

Логотип Slaschco World of Warcraft

В этой гильдии «партнеры» могут присоединиться и продать прекрасное приключенческое снаряжение Слашко многим народам Азерота, а также нанять своих друзей и семью для продажи продуктов Слашко. Когда сотрудник нанимает кого-то для вступления в гильдию, этот новый член становится частью «нисходящего потока» сотрудника. В качестве роялти за привлечение этого нового участника, партнеры будут получать небольшую комиссию за каждый предмет, проданный членами «нижестоящих» из них.

В этом графике компенсаций есть продавцы, которые будут продавать продукты напрямую, а также нанимать людей для продажи продуктов от имени Slashco. Я создал образец модели на основе популярной многоуровневой маркетинговой модели. Он состоит из четырех источников дохода:

    • Прямые продажи: за каждый предмет, который продает член команды напрямую, он зарабатывает комиссию.
    • Роялти-фри: процент, полученный от розничной цены товаров, проданных людьми «в пределах их нижнего течения», то есть тех, кого они завербовали для работы в Slashco, и, соответственно, тех, кого набрали их новобранцы.
    • Оптовая прибыль: процент, заработанный на товарах, проданных тем, кто «в пределах своей низовья» (эти товары затем будут перепроданы потребителям.
    • Мировая выручка от продаж: процент от всех продаж, сделанных теми, кто работает в Slashco (или распределение доходов).

Вот пример того, как типичная организация MLM может компенсировать своих партнеров:

Многоуровневая маркетинговая пирамида компенсаций продаж

Мы видим, что в зависимости от того, на каком уровне вы находитесь, то, как вы получаете компенсацию как за прямые продажи, так и за пассивные потоки дохода, может сильно различаться. Таким образом, расчет компенсации может быть по меньшей мере волосатым.

Если бы мы перенесли наши данные из прежнего планировщика компенсаций продаж, было бы лучше перенести все эти данные в ряд файлов .csv. В мире баз данных файлы значений, разделенных запятыми, часто являются наименьшим общим знаменателем — поэтому для 90% проектов, над которыми я работаю, я начинаю там.

Давайте представим, что мы поместили наши старые данные MySQL в серию из 3 CSV-файлов:

Это идеализированные дампы, в которых я синтезировал примерно три десятка CSV-файлов на три, просто чтобы показать пример того, как выглядят данные до и после процесса ETL в Neo4j ( LOAD CSV ).

При проверке в Excel (вы можете посмотреть их в любом другом текстовом редакторе), мы увидим серию заголовков и строк со значениями, которые соответствуют этим заголовкам. Например, на изображении ниже мы видим, что транзакция с идентификатором 1000000 имеет значение 30 под заголовком «salesRepID», 22 под заголовком «period», 7780 под заголовком «item1» и т. Д. и т. д. Нам нужно будет сказать Neo4j, как интерпретировать эту информацию в виде серии узлов и отношений вместо квадратных данных «строки и столбца».

Данные CSV для многоуровневой маркетинговой компенсации продаж

Прежде чем мы действительно загрузим какие-либо данные в Neo4j, важно знать, какие вопросы будут важны для нашего бизнеса. В этом случае мы моделируем инструмент компенсации продаж. Наши главные запросы могут быть примерно такими:

    1. Комиссия за каждого представителя, по периодам, в соответствии с правилами компенсации
    2. Комиссия за каждого представителя, ежегодно в соответствии с правилами компенсации
    3. Лидер продаж
  • Топ продаж по продажам
  • Лучший торговый представитель по крупнейшей сделке
  • Глобальная отчетность
    • Продажи по периодам
    • Самые продаваемые товары
  • рекомендации
    • Какие предметы чаще всего продаются вместе?

    Когда мы знаем эти вопросы, мы можем построить модель, которая позволяет быстро и эффективно отвечать на эти вопросы.

    Как правило, если часть данных важна для вашего прецедента «сделайте его физическим», что означает, что если вы собираетесь выполнять обход или фильтрацию на основе определенного бита информации, то сделайте его узлом или отношением.

    Например: поскольку мы знаем, что «сделки» важны для нашей таблицы лидеров продаж, мы собираемся сделать идею сделки (транзакции) конкретным типом узла. Затем мы добавим информацию об этой транзакции, например, когда она произошла, кому она принадлежит и какие элементы содержались в сделке. Тем не менее, в качестве «последнего шага» мы будем выполнять некоторые базовые математические операции над ценой, которая специфична для этого элемента, поэтому мы будем сохранять это как свойство.

    Модель данных приложения компенсации Slaschco

    Модель данных о продажах

    Скрипты, которые я использую для создания этого примера, находятся в этом git-репо .

    Теперь, когда у нас есть модель данных, давайте запустим Neo4j и передадим наш скрипт импорта (см. Здесь ). По сути, мы создаем несколько ограничений и индексов, а затем рассказываем Neo4j, как интерпретировать наши CSV-файлы в приведенной выше модели.

    Neo4j CSV Import

    Теперь, когда мы загрузили все наши данные, давайте откроем наш браузер и начнем отвечать на некоторые из наших самых популярных запросов.

    Neo4j Браузер Граф Визуализация

    Мы будем работать в обратном направлении

    5. Рекомендация

      • Какие предметы чаще всего продаются вместе?
    //recommendation engine, what items are most frequently co-sold?
    MATCH path = (item:Item)-[:CONTAINS]-(:Transaction)-[:CONTAINS]-(item2:Item)
    WHERE id(item) > id(item2)
    WITH item, item2, count(distinct path) as instances
    ORDER BY instances DESC
    LIMIT 3
    RETURN item.name, item2.name, instances;
    

    Cypher Query Рекомендации Engine

    4. Глобальная отчетность

      • Продажи по периодам
      • Самые продаваемые товары
    //total sales volume by period descending
    MATCH (p:Period)-[:OCCURED_IN]-(t:Transaction)-[:CONTAINS]-(i:Item)
    WITH sum(i.price) as sales, p
    ORDER BY sales DESC
    LIMIT 10
    RETURN sales, p.period;
    

    Cypher Query для отчетов о глобальных продажах

    MATCH (t:Transaction)-[:CONTAINS]-(i:Item)
    WITH count(distinct(t)) as itemSales, i
    ORDER BY itemSales DESC
    LIMIT 5
    RETURN i.name as name, itemSales as count;
    

    зашифровывать-запрос-Global-продажи-отчетности-2

    3. Лидер продаж

      • Топ продаж по общему объему продаж
      • Лучший торговый представитель по крупнейшей сделке
    //Who has sold the most volume?
    MATCH (rep)-[:SOLD]-(txn)-[:CONTAINS]-(itm)
    WITH rep, round(sum(itm.price)) as volume
    ORDER BY volume DESC
    LIMIT 5
    RETURN rep.name as name, volume;
    

    Cypher Query для списка лидеров продаж

    //Who closed the largest deal?
    MATCH (rep)-[:SOLD]-(txn)
    WITH rep, txn
    MATCH (txn)-[:CONTAINS]-(itm)
    WITH rep, txn, round(sum(itm.price)) as dealSize
    ORDER BY dealSize DESC
    LIMIT 5
    RETURN rep.name as name, txn.transactionID as transction, dealSize as `deal size`;
    

    зашифровывать-запрос-продаж-лидеры по величине, сделка

    2. Комиссия за каждого представителя, ежегодно в соответствии с правилами компенсации

    Из-за сложности запросов я решил запустить их с каждым уровнем повторений, выделенным в отдельный запрос, однако все они следуют базовой форме запроса «что мне делать со всем этим золотым»:

    //level 6 comp
    MATCH (transaction)-[:CONTAINS]-(item)
    WITH sum(item.price*.05) as globalRoyalty
    MATCH (big_boss:Person {level:6})<-[r:REPORTS_TO*..]-(downStreamers)-[:SOLD]-(transaction)-[:CONTAINS]-(item)
    WITH sum(item.price*.1)+sum(item.wholesalePrice*.5) + globalRoyalty as downStreamGlobal6, big_boss
    MATCH (boss)-[:SOLD]-(transaction)-[:CONTAINS]-(item)
    WITH sum(item.price*.65) + downStreamGlobal6 as tc6, big_boss.name as n6
    RETURN tc6, n6;
    

    Компенсация продаж ежегодно Neo4j Query

    1. Комиссия, взимаемая с каждого представителя, по периоду в соответствии с правилами компенсации

    Это выглядит пугающе похоже на наш последний запрос, за исключением того, что мы добавили короткий шаблон

    (transaction)-[:OCCURRED_IN]-(period {period:35})

    который отфильтрует все транзакции, которые произошли в периоды, которые не являются 35-ыми. Мы по-прежнему видим, что для набора данных разумного размера (100 сотрудников, 20 тыс. Позиций, 10 тыс. Транзакций) neo4j работает молниеносно.

    //level 6 comp with time period
    MATCH (transaction)-[:OCCURRED_IN]-(p:Period {period:35})
    WITH transaction, p
    MATCH (transaction)-[:CONTAINS]-(item)
    WITH sum(item.price*.05) as globalRoyalty, p
    MATCH (transaction)-[:OCCURRED_IN]-(p:Period {period:35})
    WITH globalRoyalty, p, transaction
    MATCH (big_boss:Person {level:6})<-[r:REPORTS_TO*..]-(downStreamers)-[:SOLD]-(transaction)-[:CONTAINS]-(item)
    WITH sum(item.price*.1)+sum(item.wholesalePrice*.5) + globalRoyalty as downStreamGlobal6, big_boss, p
    MATCH (transaction)-[:OCCURRED_IN]-(p:Period {period:35})
    WITH transaction, downStreamGlobal6, big_boss
    MATCH (boss)-[:SOLD]-(transaction)-[:CONTAINS]-(item)
    WITH sum(item.price*.65) + downStreamGlobal6 as tc6, big_boss.name as n6
    RETURN tc6, n6;
    

    Компенсация продаж по периодам, запрос Neo4j

    // КВГ

    [ Как контент сообщества, этот пост отражает взгляды и мнения конкретного автора и не обязательно отражает официальную позицию Neo4j. Этот пост был первоначально написан  Кевином Ван Ганди в блоге Кевина Ван Ганди . ]