Попытка найти лучший способ удалить элемент из словаря Firestore

Я использую Firestore в своем приложении, и у меня есть поле карты под названием «голоса» для голосов пользователей за или против. Это выглядит так:

введите здесь описание изображения

Я хочу добавить возможность удалить элемент оттуда, вот что я получил сейчас:

 //getting the user's votes dictionary and removing the post from it.
    userRef.getDocument { (doc, error) in
        if let _ = error { completion(false) }
        guard let dict = doc?.data()?[USER_VOTES] as? [String: Any] else { return }
        currentDict = dict
        currentDict.removeValue(forKey: id)
    }

    //setting the votes dictionary with the updated one.
    userRef.setData(currentDict) { (error) in
        if let _ = error { completion(false) }
        else { completion(true) }
    }

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

РЕДАКТИРОВАТЬ: я пытался удалить это так

    userRef.updateData([
        USER_VOTES:[
            id: FieldValue.delete()
        ]
    ]) { (error) in
        if let _ = error { completion(false) }
    }

Приложение вылетает пишет:

Terminating app due to uncaught exception 'FIRInvalidArgumentException', reason: 'FieldValue.delete() can only appear at the top level of your update data 

person John Doah    schedule 26.11.2019    source источник
comment
Посмотрите на использование FieldValue.delete(), чтобы вызвать отдельное поле карты для удаления. Вам нужно будет использовать точечную нотацию значения поля, чтобы идентифицировать конкретное поле (например, voices.XXX). firebase.google.com/docs/firestore/manage-data/   -  person Doug Stevenson    schedule 26.11.2019
comment
Кстати, эта архитектура данных не будет хорошо масштабироваться в Firestore, потому что этот единственный документ станет слишком большим по мере роста вашей пользовательской базы. Firestore оптимален, когда есть много мелких документов, а не наоборот. Это NoSQL в целом.   -  person liquid    schedule 26.11.2019
comment
@DougStevenson Спасибо, выглядит именно так, как я хотел!   -  person John Doah    schedule 27.11.2019
comment
@bsod Спасибо, я не думал об этом. Есть ли способ лучше? Я пытаюсь добавить опцию upvote и downvote в свое приложение.   -  person John Doah    schedule 27.11.2019
comment
@DougStevenson Я пробовал это, но это не сработало, я не смог добраться до voices.id, чтобы удалить его. Я пытался следовать документам, но это не сработало для меня.   -  person John Doah    schedule 27.11.2019
comment
Пожалуйста, отредактируйте вопрос, чтобы показать, что вы пробовали, но не сработало так, как вы ожидаете.   -  person Doug Stevenson    schedule 27.11.2019
comment
@DougStevenson Я отредактировал вопрос. Я попытался добраться до элемента, который хочу удалить, с его идентификатором. но я получаю сообщение об ошибке.   -  person John Doah    schedule 27.11.2019
comment
Похоже, вы не используете точечную запись, чтобы найти поле, как я предложил в своем первом комментарии.   -  person Doug Stevenson    schedule 27.11.2019
comment
@DougStevenson Я пытался, но USER_VOTES — это строка, и я не смог этого сделать.   -  person John Doah    schedule 28.11.2019


Ответы (1)


Чтобы иметь возможность удалить конкретное поле, выполните действия, описанные здесь< /а>.

Для вашего случая я создал следующее в коллекции «голосование»: введите здесь описание изображения

Итак, чтобы удалить поле voice2, вы должны использовать:

// Get the `FieldValue` object
let FieldValue = require('firebase-admin').firestore.FieldValue;

// Create a document reference
let fieldRef = db.collection('voting').doc('votes');

// Remove the 'vote2' field from the document 'votes'
let removeField = fieldRef.update({
  vote2: FieldValue.delete()
});

А вот документ после выполнения вышеуказанного: введите здесь описание изображения

ИЗМЕНИТЬ:

Если модель данных представляет собой карту внутри документа, например: < img src="https://i.stack.imgur.com/1SdMY.png" alt="введите здесь описание изображения">

Тогда вот как вы можете удалить поле внутри массива, который находится внутри документа:

let docRef = db.collection('voting').doc('user1');

let removeField = docRef.set({'votes':
    {['id_vote_1'] : FieldValue.delete()}}, {merge: true});

Вот документ после выполнения вышеуказанного:

введите здесь описание изображения

person Waelmas    schedule 05.12.2019
comment
Спасибо, я попробовал это, но моя проблема в том, что у меня есть пользовательский документ, внутри которого у меня есть словарь голосов. и это решение не работает для меня. - person John Doah; 06.12.2019
comment
@JohnDoah Я обновил свой ответ, показав также, как вы можете удалить поле внутри карты, которая находится внутри документа. - person Waelmas; 07.12.2019
comment
Извините, мне понадобилось несколько дней, чтобы ответить. Это работает сейчас. Большое спасибо! - person John Doah; 09.12.2019