Using the Firestore REST API to Update a Document Field

梦想的初衷 提交于 2021-02-05 10:42:51

问题


I've been searching for a pretty long time but I can't figure out how to update a field in a document using the Firestore REST API. I've looked on other questions but they haven't helped me since I'm getting a different error:

{'error': {'code': 400, 'message': 'Request contains an invalid argument.', 'status': 'INVALID_ARGUMENT', 'details': [{'@type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'field': 'oil', 'description': "Error expanding 'fields' parameter. Cannot find matching fields for path 'oil'."}]}]}}

I'm getting this error even though I know that the "oil" field exists in the document. I'm writing this in Python.

My request body (field is the field in a document and value is the value to set that field to, both strings received from user input):

{
    "fields": {
        field: {
            "integerValue": value
        }
    }
}

My request (authorizationToken is from a different request, dir is also a string from user input which controls the directory):

requests.patch("https://firestore.googleapis.com/v1beta1/projects/aethia-resource-management/databases/(default)/documents/" + dir + "?updateMask.fieldPaths=" + field, data = body, headers = {"Authorization": "Bearer " + authorizationToken}).json()

回答1:


Based on the the official docs (1,2, and 3), GitHub and a nice article, for the example you have provided you should use the following:

requests.patch("https://firestore.googleapis.com/v1beta1/projects{projectId}/databases/{databaseId}/documents/{document_path}?updateMask.fieldPaths=field")

Your request body should be:

{
    "fields": {
        "field": {
            "integerValue": Value
        }
    }
}

Also keep in mind that if you want to update multiple fields and values you should specify each one separately. Example:

https://firestore.googleapis.com/v1beta1/projects/{projectId}/databases/{databaseId}/documents/{document_path}?updateMask.fieldPaths=[Field1]&updateMask.fieldPaths=[Field2]

and the request body would have been:

{
  "fields": {
    "field": {
      "integerValue": Value
    },
    "Field2": {
      "stringValue": "Value2"
    }
  }
}

EDIT:

Here is a way I have tested which allows you to update some fields of a document without affecting the rest.

This sample code creates a document under collection users with 4 fields, then tries to update 3 out of 4 fields (which leaves the one not mentioned unaffected)

from google.cloud import firestore

db = firestore.Client()

#Creating a sample new Document “aturing” under collection “users”
doc_ref = db.collection(u'users').document(u'aturing')
doc_ref.set({
    u'first': u'Alan',
    u'middle': u'Mathison',
    u'last': u'Turing',
    u'born': 1912
})


#updating 3 out of 4 fields (so the last should remain unaffected)

doc_ref = db.collection(u'users').document(u'aturing')
doc_ref.update({
    u'first': u'Alan',
    u'middle': u'Mathison',
    u'born': 2000
})

#printing the content of all docs under users
users_ref = db.collection(u'users')
docs = users_ref.stream()

for doc in docs:
    print(u'{} => {}'.format(doc.id, doc.to_dict()))

EDIT: 10/12/2019

PATCH with REST API

I have reproduced your issue and it seems like you are not converting your request body to a json format properly.

You need to use json.dumps() to convert your request body to a valid json format.

A working example is the following:

import requests
import json

endpoint = "https://firestore.googleapis.com/v1/projects/[PROJECT_ID]/databases/(default)/documents/[COLLECTION]/[DOCUMENT_ID]?currentDocument.exists=true&updateMask.fieldPaths=[FIELD_1]"

body = {
    "fields" : {
        "[FIELD_1]" : {
            "stringValue" : "random new value"
        }
    }
}

data = json.dumps(body)

headers = {"Authorization": "Bearer [AUTH_TOKEN]"}
print(requests.patch(endpoint, data=data,  headers=headers).json())



回答2:


I found the official documentation to not to be of much use since there was no example mentioned. This is the API end-point for your firestore database

PATCH https://firestore.googleapis.com/v1beta1/projects/{YOUR_PROJECT_ID}/databases/(default)/documents/{COLLECTION_NAME}/{DOCUMENT_NAME}

the following code is the body of your API request

 {
  "fields": {
    "first_name": {
      "stringValue":"Kurt"
    },
    "name": {
      "stringValue":"Cobain"
    },
    "band": {
      "stringValue":"Nirvana"
    }
  }
}

The response you should get upon successful update of the database should look like

{
    "name": "projects/{YOUR_PROJECT_ID}/databases/(default)/documents/{COLLECTION_ID/{DOC_ID}",
    {
  "fields": {
    "first_name": {
      "stringValue":"Kurt"
    },
    "name": {
      "stringValue":"Cobain"
    },
    "band": {
      "stringValue":"Nirvana"
    }
  }
   "createTime": "{CREATE_TIME}",
    "updateTime": "{UPDATE_TIME}"

Note that performing the above action would result in a new document being created, meaning that any fields that existed previously but have NOT been mentioned in the "fields" body will be deleted. In order to preserve fields, you'll have to add

?updateMask.fieldPaths={FIELD_NAME}  --> to the end of your API call (for each individual field that you want to preserve).

For example:

PATCH https://firestore.googleapis.com/v1beta1/projects/{YOUR_PROJECT_ID}/databases/(default)/documents/{COLLECTION_NAME}/{DOCUMENT_NAME}?updateMask.fieldPaths=name&updateMask.fieldPaths=band&updateMask.fieldPaths=age. --> and so on



来源:https://stackoverflow.com/questions/59076188/using-the-firestore-rest-api-to-update-a-document-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!