От многих до многих отношений в Firebase

У меня есть база данных Firebase. У меня есть компании и подрядчики. Подрядчик может работать более чем в одной Компании, и у Компании может быть несколько Подрядчиков. Это очень много отношения ко многим. Я хочу иметь возможность ответить на вопросы о компаниях и подрядчиках:

  • Для Компании, являющихся действующими Подрядчиками.
  • Для Подрядчика, для каких компаний они работают.

Каковы альтернативы для структурирования данных в firebase?

Ответы

Ответ 1

Самопомощь - это действительно один из способов моделирования этого. Это, вероятно, самый прямой эквивалент того, как вы моделируете это в реляционной базе данных:

  • подрядчики
  • компании
  • companyAndContractorsAssignment (таблица соединений "многие-ко-многим" )

Альтернативой может быть использование 4 узлов верхнего уровня:

  • подрядчики
  • компании
  • companyContractors
  • contractorCompanies

Последние два узла будут выглядеть так:

companyContractors
    companyKey1
        contractorKey1: true
        contractorKey3: true
    companyKey2
        contractorKey2: true
contractorCompanies
    contractorKey1
        companyKey1: true
    contractorKey2
        companyKey2: true
    contractorKey3
        companyKey1: true

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

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

Рекомендуемое чтение Моделирование данных NoSQL и просмотр Firebase для разработчиков SQL. Этот вопрос также был показан в эпизоде ​​серии youtube #AskFirebase.

Обновление (2017016)

Кто-то отправил следующий вопрос, который ссылается здесь о поиске фактических предметов из узлов "подрядчиков" и "компаний". Вам нужно будет получить их по одному, поскольку Firebase не имеет эквивалента SELECT * FROM table WHERE id IN (1,2,3). Но эта операция не так медленна, как вы думаете, потому что запросы конвейерны по одному соединению. Подробнее об этом читайте здесь: Ускорьте выборку сообщений для моего приложения в социальной сети, используя запрос вместо повторного наблюдения за одним событием.

Ответ 2

После дальнейших исследований я попытаюсь ответить на свой вопрос. Я рассмотрел ряд других сообщений, и одним из решений проблемы "многие-ко-многим" является сохранение списка "Подрядчиков" в объекте "Компания" и сохранение списка "Ключи компании" в каждом объекте-подрядчике. Это проиллюстрировано на примере ниже.

companies : {
  companyKey1 : {
    name : company1
    ...
    contractors : {
      contractorKey1 : true,   
      contractorKey3 : true
    }
  }
  companyKey2 : {
    name : company2
    ...
    contractors : {
      contractorKey2 : true,  
    } 
  }
}
contrators : {
  contractorKey1 : {
     name : bill
     ...
     companies : {
        companyKey1 : true
     }
   }
  contractorKey2 : {
     name : steve
     ...
     companies : {
        companyKey1 : true
     }

   }
  contractorKey3 : {
     name : jim
     ...
     companies : {
        companyKey2 : true
     }
   }
}

Эта организация "работает" в том смысле, что на вышеупомянутые вопросы можно ответить. Но недостатком этого решения является то, что есть два списка для поддержки, когда изменения Подрядчика/Компании меняются. Было бы лучше, если бы был способ представить эту информацию в одном списке.

Думаю, я придумал лучшее решение. Решение заключается в создании третьего списка, в дополнение к компаниям и подрядчикам, называемым companyAndContractorAssignment. Элементы этого списка будут представлять собой отношения между одним подрядчиком и компанией. Его содержимым будет пара полей, подрядчикKey и компанияKey. Затем мы можем исключить список подрядчиков внутри компании и список компаний в рамках подрядчика. Эта альтернативная структура представлена ​​ниже. Обратите внимание, что в объекте компании нет списка подрядчиков, и нет списка компаний с объектом подрядчика.

companies : {
  companyKey1 : {
    name : company1
    ...
  }
  companyKey2 : {
    name : company2
    ...
  }
}
contrators : {
  contractorKey1 : {
     name : bill
     ...
  }
  contractorKey2 : {
     name : steve
     ...
  }
  contractorKey3 : {
     name : jim
     ...
  }
}
companyAndContractorsAssignment : {
  key1 : {
    contractorKey1 : true,
    companyKey1: true,
  }
  key2 : {
    contractorKey3 : true,
    companyKey1: true,
  }
  key3 : {
    contractorKey2 : true,
    companyKey2: true,
  }

Эта альтернативная структура позволяет ответить на вопросы, используя запрос orderByChild/equalTo на companyAndContractorsAssignment, чтобы найти все компании для подрядчика или всех подрядчиков для компании. И теперь есть только один список для поддержки. Я думаю, что это лучшее решение для моих требований.