Zapisywanie danych

Sposoby zapisywania danych

UMIEŚCIĆ Zapisz lub zamień dane w określonej ścieżce , np fireblog/users/user1/<data>
SKRAWEK Zaktualizuj niektóre klucze dla określonej ścieżki bez zastępowania wszystkich danych.
POST Dodaj do listy danych w naszej bazie danych Firebase. Za każdym razem, gdy wysyłamy żądanie POST , klient Firebase generuje unikalny klucz, taki jak fireblog/users/<unique-id>/<data>
USUWAĆ Usuń dane z określonego odniesienia do bazy danych Firebase.

Zapisywanie danych za pomocą PUT

Podstawową operacją zapisu poprzez API REST jest PUT . Aby zademonstrować zapisywanie danych, zbudujemy aplikację do blogowania z postami i użytkownikami. Wszystkie dane naszej aplikacji będą przechowywane w ścieżce `fireblog`, pod adresem URL bazy danych Firebase `https://docs-examples.firebaseio.com/fireblog`.

Zacznijmy od zapisania niektórych danych użytkownika w naszej bazie danych Firebase. Będziemy przechowywać każdego użytkownika pod unikalną nazwą użytkownika, a także będziemy przechowywać jego pełne imię i nazwisko oraz datę urodzenia. Ponieważ każdy użytkownik będzie miał unikalną nazwę użytkownika, sensowne jest użycie tutaj PUT zamiast POST , ponieważ mamy już klucz i nie musimy go tworzyć.

Za pomocą PUT możemy zapisać ciąg znaków, liczbę, wartość logiczną, tablicę lub dowolny obiekt JSON do naszej bazy danych Firebase. W tym przypadku przekażemy mu obiekt:

curl -X PUT -d '{
  "alanisawesome": {
    "name": "Alan Turing",
    "birthday": "June 23, 1912"
  }
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'

Kiedy obiekt JSON jest zapisywany w bazie danych, właściwości obiektu są automatycznie mapowane na lokalizacje podrzędne w sposób zagnieżdżony. Jeśli przejdziemy do nowo utworzonego węzła, zobaczymy wartość „Alan Turing”. Możemy także zapisać dane bezpośrednio w lokalizacji podrzędnej:

curl -X PUT -d '"Alan Turing"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'

Powyższe dwa przykłady – zapisanie wartości jednocześnie z obiektem i zapisanie ich osobno w lokalizacjach podrzędnych – spowodują zapisanie tych samych danych w naszej bazie danych Firebase:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    }
  }
}

Pomyślne żądanie zostanie zasygnalizowane kodem stanu HTTP 200 OK , a odpowiedź będzie zawierać dane, które zapisaliśmy do bazy danych. Pierwszy przykład wyzwoli tylko jedno zdarzenie na klientach oglądających dane, podczas gdy drugi przykład wyzwoli dwa. Należy zauważyć, że jeśli dane już istniały na ścieżce użytkownika, pierwsze podejście spowodowałoby ich nadpisanie, ale druga metoda zmodyfikowałaby jedynie wartość każdego oddzielnego węzła podrzędnego, pozostawiając inne elementy podrzędne bez zmian. PUT jest odpowiednikiem set() w naszym zestawie SDK JavaScript.

Aktualizacja danych za pomocą PATCH

Korzystając z żądania PATCH , możemy zaktualizować określone elementy podrzędne w lokalizacji bez nadpisywania istniejących danych. Dodajmy pseudonim Turinga do jego danych użytkownika z żądaniem PATCH :

curl -X PATCH -d '{
  "nickname": "Alan The Machine"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Powyższa prośba spowoduje dopisanie nickname do naszego alanisawesome obiektu bez usuwania name i birthday dzieci. Należy pamiętać, że gdybyśmy zamiast tego wystawili w tym miejscu żądanie PUT , name i birthday zostałyby usunięte, ponieważ nie zostały uwzględnione w żądaniu. Dane w naszej bazie danych Firebase wyglądają teraz tak:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    }
  }
}

Pomyślne żądanie zostanie zasygnalizowane kodem stanu HTTP 200 OK , a odpowiedź będzie zawierać zaktualizowane dane zapisane w bazie danych.

Firebase obsługuje także aktualizacje wielościeżkowe. Oznacza to, że PATCH może teraz aktualizować wartości w wielu lokalizacjach w bazie danych Firebase w tym samym czasie, co jest potężną funkcją, która pozwala pomóc w denormalizacji danych . Korzystając z aktualizacji wielościeżkowych, możemy dodać pseudonimy zarówno do Alana, jak i Grace w tym samym czasie:

curl -X PATCH -d '{
  "alanisawesome/nickname": "Alan The Machine",
  "gracehopper/nickname": "Amazing Grace"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Po tej aktualizacji dodano pseudonimy zarówno Alanowi, jak i Grace:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper",
      "nickname": "Amazing Grace"
    }
  }
}

Należy pamiętać, że próba aktualizacji obiektów poprzez zapisanie obiektów z dołączonymi ścieżkami spowoduje inne zachowanie. Przyjrzyjmy się, co się stanie, jeśli zamiast tego spróbujemy zaktualizować Grace i Alana w ten sposób:

curl -X PATCH -d '{
  "alanisawesome": {"nickname": "Alan The Machine"},
  "gracehopper": {"nickname": "Amazing Grace"}
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Powoduje to inne zachowanie, a mianowicie nadpisanie całego węzła /fireblog/users :

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

Aktualizowanie danych za pomocą żądań warunkowych

Możesz użyć żądań warunkowych, odpowiednika transakcji REST, aby zaktualizować dane zgodnie z ich obecnym stanem. Na przykład, jeśli chcesz zwiększyć licznik głosów za i mieć pewność, że liczba dokładnie odzwierciedla wiele jednoczesnych głosów za, użyj żądania warunkowego, aby zapisać nową wartość w liczniku. Zamiast dwóch zapisów, które zmieniają licznik na tę samą liczbę, jedno z żądań zapisu kończy się niepowodzeniem i można następnie ponowić żądanie z nową wartością.
  1. Aby wykonać żądanie warunkowe w lokalizacji, uzyskaj unikalny identyfikator bieżących danych w tej lokalizacji lub element ETag. Jeśli dane ulegną zmianie w tej lokalizacji, zmieni się także ETag. Możesz zażądać ETag za pomocą dowolnej metody innej niż PATCH . W poniższym przykładzie zastosowano żądanie GET .
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    
    Konkretne wywołanie ETag w nagłówku zwraca ETag określonej lokalizacji w odpowiedzi HTTP.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    10 // Current value of the data at the specified location
    
  2. Dołącz zwrócony ETag do następnego żądania PUT lub DELETE , aby zaktualizować dane, które konkretnie pasują do tej wartości ETag. Idąc za naszym przykładem, aby zaktualizować licznik do 11 lub o 1 więcej niż pobrana początkowo wartość 10 i zakończyć żądanie, jeśli wartość już nie pasuje, użyj następującego kodu:
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    
    Jeśli wartość danych w określonym lokalizacja nadal wynosi 10, ETag w żądaniu PUT pasuje i żądanie kończy się pomyślnie, zapisując 11 w bazie danych.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    Cache-Control: no-cache
    
    11 // New value of the data at the specified location, written by the conditional request
    
    Jeśli lokalizacja nie jest już zgodna ze znacznikiem ETag, co może mieć miejsce, gdy inny użytkownik zapisze nową wartość do bazy danych, żądanie nie powiedzie się bez zapisu do lokalizacji. Odpowiedź zwrotna zawiera nową wartość i ETag.
    HTTP/1.1 412 Precondition Failed
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    12 // New value of the data at the specified location
    
  3. Skorzystaj z nowych informacji, jeśli zdecydujesz się ponowić żądanie. Baza danych czasu rzeczywistego nie ponawia automatycznie żądań warunkowych, które zakończyły się niepowodzeniem. Można jednak użyć nowej wartości i znacznika ETag do zbudowania nowego żądania warunkowego z informacjami zwróconymi w odpowiedzi na niepowodzenie.

Żądania warunkowe oparte na protokole REST implementują standard HTTP if-match . Różnią się jednak od standardu w następujący sposób:

  • Dla każdego żądania dopasowania można podać tylko jedną wartość ETag, a nie wiele.
  • Chociaż standard sugeruje, że znaczniki ETag powinny być zwracane ze wszystkimi żądaniami, baza danych Realtime Database zwraca znaczniki ETag tylko z żądaniami zawierającymi nagłówek X-Firebase-ETag . Zmniejsza to koszty rozliczeń w przypadku standardowych żądań.

Żądania warunkowe mogą być również wolniejsze niż typowe żądania REST.

Zapisywanie list danych

Aby wygenerować unikalny klucz oparty na sygnaturze czasowej dla każdego dziecka dodanego do odniesienia do bazy danych Firebase, możemy wysłać żądanie POST . W przypadku naszej ścieżki users sensowne było zdefiniowanie własnych kluczy, ponieważ każdy użytkownik ma unikalną nazwę użytkownika. Jednak gdy użytkownicy dodadzą posty na blogu do aplikacji, użyjemy żądania POST , aby automatycznie wygenerować klucz dla każdego wpisu na blogu:

curl -X POST -d '{
  "author": "alanisawesome",
  "title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'

Nasza ścieżka posts zawiera teraz następujące dane:

{
  "posts": {
    "-JSOpn9ZC54A4P4RoqVa": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

Zauważ, że klucz -JSOpn9ZC54A4P4RoqVa został dla nas wygenerowany automatycznie, ponieważ użyliśmy żądania POST . Pomyślne żądanie zostanie zasygnalizowane kodem stanu HTTP 200 OK , a odpowiedź będzie zawierać klucz nowych dodanych danych:

{"name":"-JSOpn9ZC54A4P4RoqVa"}

Usuwanie danych

Aby usunąć dane z bazy możemy wysłać żądanie DELETE z adresem URL ścieżki, z której chcemy usunąć dane. Poniższe polecenie usunie Alana ze ścieżki users :

curl -X DELETE \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Pomyślne żądanie DELETE będzie sygnalizowane kodem stanu HTTP 200 OK z odpowiedzią zawierającą JSON null .

Parametry URI

API REST podczas zapisu danych do bazy danych akceptuje następujące parametry URI:

autoryzacja

Parametr żądania auth umożliwia dostęp do danych chronionych regułami bezpieczeństwa bazy danych Firebase Realtime i jest obsługiwany przez wszystkie typy żądań. Argumentem może być nasz sekret aplikacji Firebase lub token uwierzytelniający, co omówimy w sekcji autoryzacja użytkownika . W poniższym przykładzie wysyłamy żądanie POST z parametrem auth , gdzie CREDENTIAL jest albo naszym sekretem aplikacji Firebase, albo tokenem uwierzytelniającym:

curl -X POST -d '{"Authenticated POST request"}' \
  'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

wydrukować

Parametr print pozwala nam określić format naszej odpowiedzi z bazy danych. Dodanie print=pretty do naszego żądania zwróci dane w formacie czytelnym dla człowieka. print=pretty jest obsługiwany przez żądania GET , PUT , POST , PATCH i DELETE .

Aby wyłączyć dane wyjściowe z serwera podczas zapisywania danych, możemy dodać do naszego żądania print=silent . Wynikowa odpowiedź będzie pusta i będzie oznaczona kodem stanu HTTP 204 No Content , jeśli żądanie zakończy się pomyślnie. Funkcja print=silent jest obsługiwana przez żądania GET , PUT , POST i PATCH .

Zapisywanie wartości serwera

Wartości serwera można zapisać w lokalizacji przy użyciu wartości zastępczej, która jest obiektem z pojedynczym kluczem ".sv" . Wartość tego klucza to typ wartości serwera, który chcemy ustawić. Na przykład, aby ustawić znacznik czasu podczas tworzenia użytkownika, możemy wykonać następujące czynności:

curl -X PUT -d '{".sv": "timestamp"}' \
  'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'

"timestamp" to jedyna obsługiwana wartość serwera i jest to czas od epoki UNIX w milisekundach.

Poprawa wydajności zapisu

Jeśli zapisujemy duże ilości danych w bazie danych, możemy użyć parametru print=silent aby poprawić wydajność zapisu i zmniejszyć wykorzystanie przepustowości. W przypadku normalnego zapisu serwer odpowiada zapisanymi danymi JSON. Jeśli określono print=silent , serwer natychmiast zamyka połączenie po odebraniu danych, zmniejszając wykorzystanie przepustowości.

W przypadku, gdy wysyłamy wiele żądań do bazy danych, możemy ponownie wykorzystać połączenie HTTPS, wysyłając żądanie Keep-Alive w nagłówku HTTP.

Warunki błędu

Interfejs API REST zwróci kody błędów w następujących okolicznościach:

Kody stanu HTTP
400 Złych żądań

Jeden z następujących warunków błędu:

  • Nie można przeanalizować danych PUT lub POST .
  • Brak danych PUT lub POST .
  • Żądanie podejmuje próbę przesłania zbyt dużych danych PUT lub POST .
  • Wywołanie interfejsu API REST zawiera w ścieżce nieprawidłowe nazwy podrzędne.
  • Ścieżka wywołania interfejsu API REST jest za długa.
  • Żądanie zawiera nierozpoznaną wartość serwera.
  • Indeks zapytania nie jest zdefiniowany w regułach bezpieczeństwa bazy danych Firebase Realtime .
  • Żądanie nie obsługuje jednego z podanych parametrów zapytania.
  • Żądanie łączy parametry zapytania z płytkim żądaniem GET .
401 Nieautoryzowane

Jeden z następujących warunków błędu:

404 Nie Znaleziono Nie znaleziono określonej bazy danych Firebase.
500 wewnętrzny błąd serwera Serwer zwrócił błąd. Dalsze szczegóły znajdziesz w komunikacie o błędzie.
503 Usługa niedostępna Podana baza danych Firebase Realtime jest tymczasowo niedostępna, co oznacza, że ​​nie podjęto próby żądania.

Zabezpieczanie danych

Firebase ma język bezpieczeństwa, który pozwala nam określić, którzy użytkownicy mają dostęp do odczytu i zapisu w różnych węzłach naszych danych. Więcej na ten temat możesz przeczytać w artykule Reguły bezpieczeństwa baz danych w czasie rzeczywistym .

Teraz, gdy omówiliśmy zapisywanie danych, w następnej sekcji możemy dowiedzieć się, jak odzyskać nasze dane z bazy danych Firebase za pośrednictwem interfejsu API REST.