Как добавить / удалить элементы массива в документе Firestore через REST? - PullRequest
0 голосов
/ 26 февраля 2020

Я хочу использовать массив для хранения показаний температуры из Arduino в базе данных Firestore. Мой (возможно, ужасный) способ до сих пор думать об этом - читать документ, выполнять операции над массивами на Arduino и отправлять весь массив обратно в Firestore. Я вообще не знаю, как писать в Firestore через REST, поэтому я еще не реализовал это. Вот мой код:

void writeTemp(String url, int temperature) {
    // writeTemp() appends the given temperature to an array. temperature[0]
    // holds the oldest temperature while temperature[9] holds the first.
    // When a new temperature is put in, the last one is taken out.
    HTTPClient http;

    http.begin(url);
    int httpCode = http.GET();

    // Gets the current temperature array from the provided URL.
    String payload = http.getString();
    Serial.println(httpCode);  // Prints HTTP response code.

    // Calculates the size of the JSON buffer. This is big enough for 11
    // temperature values that are all 3 digits so as long as you're not using
    // this on the Sun you're probably fine.
    const size_t capacity = JSON_ARRAY_SIZE(11) + 14 * JSON_OBJECT_SIZE(1) +
                            JSON_OBJECT_SIZE(4) + 440;

    DynamicJsonDocument doc(capacity);  // Makes the JSON document
    DeserializationError err = deserializeJson(doc, payload);

    // Prints out the deserialization error if an error occurred
    if (err) {
        Serial.print("JSON DESERIALIZE ERROR: ");
        Serial.println(err.c_str());
    }

    // Sets up the array from the JSON
    JsonArray temperatureArray =
        doc["fields"]["Temperature"]["arrayValue"]["values"];

    // Creates a new array object to store the new temperature
    JsonObject newTemp = temperatureArray.createNestedObject();

    // Puts the new temperature in the new array object. For some reason,
    // Firestore stores numbers as strings so the temperature is converted into
    // a string.
    newTemp["integerValue"] = String(temperature);

    // Removes the first (oldest) array object.
    temperatureArray.remove(0);

    // Removes irrelevant data that we got from the Firestore request
    doc.remove("name");
    doc.remove("createTime");
    doc.remove("updateTime");

    String newJson;
    serializeJson(doc, newJson);
    Serial.println(newJson);
}

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

firestore layout

1 Ответ

1 голос
/ 27 февраля 2020

Документация для API FESTtore REST здесь .

Чтобы создать документ, необходимо отправить запрос POST на URL в следующем формате:

https://firestore.googleapis.com/v1/{parent=projects/*/databases/*/documents/**}/{collectionId}

С экземпляром Document в теле запроса.


Чтобы быть более конкретным, ниже приведен пример на простой странице HTML (с использованием библиотека Ax ios для выдачи HTTP-запроса). Этот код создаст новый документ в коллекции collection1 Firestore.

Просто сохраните этот файл на локальном диске, измените значение <yourprojectID> и откройте эту страницу в браузере прямо с локального диска.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  </head>

  <body>
    <script>
      var firebaseProjectId = '<yourprojectID>';

      var collectionId = 'collection1';

      var url =
        'https://firestore.googleapis.com/v1/projects/' +
        firebaseProjectId +
        '/databases/(default)/documents/' +
        collectionId;

      var writeObj = {
        fields: {
          name: {
            stringValue: 'theName'
          },
          initialBudget: {
            doubleValue: 1200
          }
        }
      };

      axios.post(url, writeObj).catch(function(error) {
        console.log(error);
      });
    </script>
  </body>
</html>

Для того, чтобы чтобы обновить массив в существующем документе, вы должны использовать FieldTransform с appendMissingElements элементами.

Выдержка из этого do c для appendMissingElements элементов:

appendMissingElements: добавить данные элементы по порядку, если они еще не присутствуют в текущем значении поля. Если поле не является массивом или если поле еще не существует, для него сначала устанавливается пустой массив.

Ниже приведен пример значения FieldTransform, содержащего appendMissingElements elements.

    {
           "transform": {
            "document": "projects/" + firebaseProjectId + "/databases/(default)/documents/....,
            "fieldTransforms": [
             {
              "setToServerValue": "REQUEST_TIME",
              "fieldPath": "lastUpdate"
             },
             {
              "appendMissingElements": {
               "values": [
                {
                 "stringValue": "...."
                }
               ]
              },
              "fieldPath": "fieldName"
             }
            ]
           }
      }

ОБНОВЛЕНИЕ СЛЕДУЕТ ЗА ВАШИМ КОММЕНТАРИЕМ

Должно работать следующее (проверено положительно):

  var collectionId = 'SensorData';

  var url =
    'https://firestore.googleapis.com/v1/projects/' +
    firebaseProjectId +
    '/databases/(default)/documents:commit';

  var writeObj = {
    writes: {
      transform: {
        document:
          'projects/' +
          firebaseProjectId +
          '/databases/(default)/documents/' +
          collectionId +
          '/Temperature',
        fieldTransforms: [
          {
            setToServerValue: 'REQUEST_TIME',
            fieldPath: 'lastUpdate'
          },
          {
            appendMissingElements: {
              values: [
                {
                  integerValue: 25
                }
              ]
            },
            fieldPath: 'Temperature'
          }
        ]
      }
    }
  };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...