I dont't know update a document in Firestore

Describe the problem/error/question

Hi everyone,

I’m having trouble with the Firestore node in n8n, specifically with the Create or Update option. It’s not working as expected, or I may not be configuring it correctly for my case.

My goal is to update specific fields in an existing document in Firestore without creating a new document or completely overwriting the existing one. I’ve tried several configurations, but I can’t get it to update only the fields I want.

Could anyone guide me on how to set up this option correctly? Any advice or examples would be greatly appreciated.

Thanks!

Please share your workflow

{
  "meta": {
    "instanceId": "47995e538fdfca2fa258868e7d110240abef7462125be424d0dd4c75a168be04"
  },
  "nodes": [
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "propertyCode",
              "value": "={{ $json.adid }}{{ $json.ad.adid }}"
            },
            {
              "name": "API_status",
              "value": "={{ $json.httpStatus }}"
            },
            {
              "name": "updated",
              "value": "={{ new Date($json.ad.lastDeactivationDate).toISOString() }}"
            },
            {
              "name": "city",
              "value": "={{ $('Execute Workflow Trigger').item.json.city }}"
            },
            {
              "name": "municipioID",
              "value": "={{ $('Execute Workflow Trigger').item.json.municipioID }}"
            },
            {
              "name": "idDocument",
              "value": "={{ $('Execute Workflow Trigger').item.json.idDocument }}"
            }
          ],
          "number": [
            {
              "name": "price",
              "value": 900
            }
          ]
        },
        "options": {}
      },
      "id": "d81bbe55-d4b3-4f10-873a-c640c145d799",
      "name": "Input2",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        100,
        280
      ]
    },
    {
      "parameters": {},
      "id": "752ce1ea-6d35-4fd7-9ff3-0fcf37498dfd",
      "name": "Execute Workflow Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1,
      "position": [
        -360,
        280
      ],
      "notesInFlow": false,
      "retryOnFail": true
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.price }}",
              "operation": "isEmpty"
            },
            {
              "value1": "={{ $json.adid_resultsHTTP }}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "id": "540c0c8b-d672-4328-8872-d6cc57fab799",
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        360,
        280
      ],
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "1da6a668-5c67-4914-bbe3-3f76e2544b65",
              "leftValue": "={{ $json.price }}",
              "rightValue": "",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "3fd5a8bb-a612-4c15-8f01-687612a20797",
      "name": "Filter1",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        540,
        480
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "013a3000-4f53-4bf4-8ead-98917e23e761",
              "leftValue": "={{ $('Execute Workflow Trigger').item.json.price }}",
              "rightValue": "=\"{{ $json.price }}\"",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "31438319-0fb1-4a1c-a1b4-d626d312b519",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        760,
        480
      ]
    },
    {
      "parameters": {
        "operation": "getAll",
        "projectId": "apaloom-76827",
        "collection": "={{ $json.city }}/{{ $json._id }}/properties",
        "returnAll": true
      },
      "id": "237d0f9e-9262-40d9-a5ff-bfdae7b3338f",
      "name": "Google Cloud Firestore",
      "type": "n8n-nodes-base.googleFirebaseCloudFirestore",
      "typeVersion": 1,
      "position": [
        760,
        260
      ],
      "alwaysOutputData": false,
      "notesInFlow": false
    },
    {
      "parameters": {
        "content": "## Sin probar",
        "height": 231,
        "width": 302,
        "color": 3
      },
      "id": "249f3649-7236-4841-9926-4651924740a8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        480,
        180
      ]
    },
    {
      "parameters": {
        "jsCode": "const axios = require('axios');\n\nconst apiKey = \"AIzaSyD7Sm-BAiu326aS9Q1X1YaX-p0ZV48SLJY\";\nconst projectId = \"apaloom-76827\";\n\n// Datos de la propiedad, obtenidos de la entrada del nodo\nconst properties = $input.all();\n\nasync function updateFirestoreDocument(property) {\n  const documentPath = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${property.city}/${property.municipioID}/properties/${property.idDocument}?key=${apiKey}`;\n\n  const dataToUpdate = {\n    fields: {\n      price: { integerValue: property.price }, // No necesitas convertir a string\n      API_status: { integerValue: property.API_status },\n      updated: { timestampValue: property.updated }\n    }\n  };\n\n  try {\n    const response = await axios.patch(documentPath, dataToUpdate, {\n      headers: {\n        'Content-Type': 'application/json'\n      }\n    });\n    return response.data;\n  } catch (error) {\n    return { error: error.response.data }; // Muestra el error detallado\n  }\n}\n\nreturn Promise.all(properties.map(property => updateFirestoreDocument(property.json)));\n"
      },
      "id": "3899eafb-e755-4c1e-a5a3-242dc58a22af",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        980,
        460
      ]
    },
    {
      "parameters": {
        "content": "### No se actualiza, siempre crea uno diferente",
        "height": 231,
        "width": 250.3441560155237,
        "color": 3
      },
      "id": "1419b179-ee1a-458b-ad50-f79a3aecbe55",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -160,
        220
      ]
    },
    {
      "parameters": {
        "operation": "upsert",
        "projectId": "=apaloom-76827",
        "collection": "={{ $json.city }}/{{ $json.municipioID }}/properties",
        "updateKey": "={{ $json.idDocument }}",
        "columns": "price,API_status,updated"
      },
      "id": "d9521698-67e0-4f30-9ffa-2b3e2d27c228",
      "name": "Google Cloud Firestore1",
      "type": "n8n-nodes-base.googleFirebaseCloudFirestore",
      "typeVersion": 1,
      "position": [
        980,
        460
      ],
      "alwaysOutputData": false,
      "notesInFlow": false,
      "credentials": {
        "googleFirebaseCloudFirestoreOAuth2Api": {
          "id": "h3nPNfhJd1OSZw7a",
          "name": "Firebase Producción"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "return [\n  {\n    \"message\": \"ad not found\",\n    \"httpStatus\": 404,\n    \"ad\": {\n      \"adid\": 37714764,\n      \"operation\": \"rent\",\n      \"propertyType\": \"homes\",\n      \"locationId\": \"0-EU-ES-28-06-005-148-02\",\n      \"lastDeactivationDate\": 1729677945000,\n      \"suggestedTitle\": \"Piso en calle Platino, Sureste, Torrejón de Ardoz\",\n      \"locationText\": \"Sureste, Torrejón de Ardoz\",\n      \"translatedTexts\": {\n        \"characteristicsDescriptions\": [\n          {\n            \"key\": \"features\",\n            \"title\": \"Características básicas\",\n            \"detailFeatures\": [\n              {\n                \"phrase\": \"60 m² construidos\"\n              },\n              {\n                \"phrase\": \"1 habitación\"\n              }\n            ]\n          },\n          {\n            \"key\": \"costs\",\n            \"title\": \"Precio\",\n            \"detailFeatures\": [\n              {\n                \"phrase\": \"800 €/mes\"\n              }\n            ]\n          }\n        ]\n      },\n      \"deactivationReason\": \"user\",\n      \"isAuction\": false,\n      \"tracking\": {\n        \"unsubscriptionId\": 26,\n        \"isSuitableForRecommended\": true,\n        \"stateCode\": \"A\",\n        \"commercialDataId\": 130165348\n      },\n      \"allowsRecommendation\": true,\n      \"contactInfo\": {\n        \"commercialName\": \"Punto Inmobiliario del Henares\",\n        \"phone1\": {\n          \"phoneNumber\": \"919382670\",\n          \"formattedPhone\": \"919 38 26 70\",\n          \"prefix\": \"34\",\n          \"phoneNumberForMobileDialing\": \"+34919382670\",\n          \"nationalNumber\": true,\n          \"formattedPhoneWithPrefix\": \"+34 919 38 26 70\"\n        },\n        \"contactName\": \"Maria Luisa\",\n        \"externalReference\": \"415\",\n        \"userType\": \"professional\",\n        \"agencyLogo\": \"https://st3.idealista.com/f1/96/e1/punto-inmobiliario-del-henares.gif\",\n        \"contactMethod\": \"all\",\n        \"micrositeShortName\": \"punto-inmobiliario-del-henares\",\n        \"address\": {\n          \"streetName\": \"Hilados\",\n          \"streetNumber\": 1,\n          \"locationName\": \"Torrejón de ardoz\",\n          \"postalCode\": \"28850\"\n        },\n        \"agentInfo\": {\n          \"name\": \"Maria Luisa\",\n          \"proAgent\": false\n        },\n        \"inVirtualMicrosite\": false,\n        \"corporatePhrase\": {\n          \"text\": \"Somos una empresa seria y responsable, nos preocupamos por nuestro clientes y damos el mejor servicio de venta y alquileres de inmuebles\",\n          \"autoTranslated\": false\n        },\n        \"totalAds\": 0,\n        \"professional\": true\n      },\n      \"price\": 800,\n      \"rooms\": 1,\n      \"size\": 60\n    }\n  }\n]"
      },
      "id": "32958e30-efc0-43be-9e57-3862668dcca4",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -100,
        280
      ]
    }
  ],
  "connections": {
    "Input2": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow Trigger": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "Google Cloud Firestore",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Filter1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter1": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "Google Cloud Firestore1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Input2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {
    "Execute Workflow Trigger": [
      {
        "propertyCode": 37714764,
        "city": "Madrid",
        "price": "800",
        "idDocument": "ThP3W6ssXEc0OkZYQXvs",
        "API_status": null,
        "town": "Torrejón de Ardoz",
        "municipioID": "4GjBgg8BerAu5T03H46e"
      }
    ]
  }
}```

## Share the output returned by the last node


<!-- If you need help with data transformations, please also share your expected output. -->

## Information on your n8n setup
- **n8n version:** 1.64.0
- **n8n EXECUTIONS_PROCESS setting (default: own, main):**
- **Running n8n via (Docker, npm, n8n cloud, desktop app):** npm in local
- **Operating system:** Windows

It looks like your topic is missing some important information. Could you provide the following if applicable.

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:
  • n8n version: 1.64.0
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app): npm in local
  • Operating system: Windows

Cand you help me @Jon @bartv ?

Hello, I had a Firestore project some moths ago. If I rember it correctly to update some values you need to refer to the Firestore API. And use the http request node.

Hi @sfx thanks for replying, I can’t find in the documentation what kind of call I should make to update a document? I can only find information using your library, but not via API

Do you have an example please?

I dont have something at the moment. But you need the exact endpoint of the firestore doc and then the json structure as boffy. I would build a sandbox workflow in your case and play a bit arround. And perhaps ask ChatGPT for help.

Hi @sfx

Do you remember if you had any permission issue. With the next code…

const { Firestore } = require('@google-cloud/firestore');

const firestore = new Firestore({
  projectId: 'apaloom-XXXX',
  keyFilename: 'C:/Users/YY/Documents/n8n/unique-terminus-kjkjkjk.json' // Asegúrate de que la ruta es correcta
});


// Ejemplo de obtener documentos
const snapshot = await firestore.collection('Madrid').get();
snapshot.forEach(doc => {
  console.log(doc.id, '=>', doc.data());
});

return [];

I had the next issue. I configure in Google Cloud the admin role

Error: 7 PERMISSION_DENIED: Missing or insufficient permissions. at callErrorFromStatus (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@grpc\grpc-js\src\call.ts:82:17) at Object.onReceiveStatus (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@grpc\grpc-js\src\client.ts:612:51) at Object.onReceiveStatus (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@grpc\grpc-js\src\client-interceptors.ts:419:48) at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@grpc\grpc-js\src\resolving-call.ts:163:24 at processTicksAndRejections (node:internal/process/task_queues:77:11) for call at at ServiceClientImpl.makeServerStreamRequest (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@grpc\grpc-js\src\client.ts:595:42) at ServiceClientImpl.<anonymous> (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@grpc\grpc-js\src\make-client.ts:189:15) at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\v1\firestore_client.js:237:29 at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\google-gax\build\src\streamingCalls\streamingApiCaller.js:38:28 at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\google-gax\build\src\normalCalls\timeout.js:44:16 at Object.request (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\google-gax\build\src\streamingCalls\streaming.js:376:40) at makeRequest (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\retry-request\index.js:159:28) at retryRequest (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\retry-request\index.js:119:5) at StreamProxy.setStream (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\google-gax\build\src\streamingCalls\streaming.js:367:37) at StreamingApiCaller.call (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\google-gax\build\src\streamingCalls\streamingApiCaller.js:54:16) Caused by: Error: at QueryUtil._getResponse (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\reference\query-util.js:43:23) at CollectionReference._getResponse (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\reference\query.js:784:32) at CollectionReference._get (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\reference\query.js:777:35) at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\reference\query.js:745:43 at DisabledTraceUtil.startActiveSpan (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\telemetry\disabled-trace-util.js:16:16) at CollectionReference.get (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@google-cloud\firestore\build\src\reference\query.js:744:43) at VM2 Wrapper.apply (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@n8n\vm2\lib/bridge.js:490:11) at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\n8n-nodes-base\dist\nodes\Code:10:55 at C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\n8n-nodes-base\dist\nodes\Code:16:2 at VM2 Wrapper.apply (C:\Users\fvalv\AppData\Roaming\npm\node_modules\n8n\node_modules\@n8n\vm2\lib\bridge.js:490:11)

I’m having the same problem. I think the N8N update module is broken as you are correct, it overwrites the existing content.

I can get around it using an http request and it does make it simpler in that you can still use your Firestore credentials. The trick is you need to send an updateMask in your Query Parameters with the field names (separated by commas) and the body with the field info. I had to put a code module before it to format the stuff the way Firestore expected.

It’s really clunky though… I think @n8n really should just fix their version of a “patch” request.