Я создаю чат-приложение 1-к-1 с Firestore и Javascript (vue.js).
У меня есть разговор и документ сообщения, определенные следующим образом:
.collection ( "coversation"). Док ()
conversation: {
participantsArray: ["id1", "id2"],
participants: {
id1: {
/* details like avatar & name */
},
id2: {
/* details like avatar & name */
}
}
}
.collection ( "coversation"). Документ ( "Foo"). Коллекция ( "сообщения"). Док ()
message: {
message: "foo"
}
Это здорово, поэтому теперь я могу запрашивать все разговоры определенного пользователя, например:
db.collection('conversations').where("participantsArray", "array-contains", userId)
У меня возникла следующая проблема:
Я хочу запросить конкретную беседу, вот так:
db.collection('conversations')
.where("participantsArray", "array-contains", userId)
.where("participantsArray", "array-contains", chatpartnerId)
Но это не работает, поскольку двойное "array-contains" не разрешено и выдает сообщение об ошибке.
Сейчас у меня работает два звонка:
db.collection('conversations')
.where(`participantsArray`, '==', [userId, chatpartnerId])
db.collection('conversations')
.where(`participantsArray`, '==', [chatpartnerId, userId])
и затем проверьте, возвращает ли какой-либо из этих запросов разговор. Если это так, я использую этот разговор для добавления сообщения, в противном случае я создаю новый разговор.
Это работает, но это куча кода и довольно неэффективно.
Так что мой вопрос будет:
- Есть ли лучший способ сделать это?
- Как сделать "массив-содержимое", чтобы проверить наличие нескольких элементов?
- У меня есть и поле membersArray , и поле members , потому что я не понял, как сделать "array-contains" в массиве объектов. Есть ли способ или я должен оставить оба поля?
PS:
Раньше я делал запросы к объектам в объекте участников так:
db.collection("conversations").where(`participants.${userId}.id`, "==", userId)
Это был предложенный способ запроса до появления «массива-содержимого», но в сочетании с orderBy мне пришлось бы создавать индекс для каждого пользователя, что на самом деле не вариант.