firebase-tools icon indicating copy to clipboard operation
firebase-tools copied to clipboard

Firestore emulator doesn't properly handle nested vector fields

Open jellynoone opened this issue 1 year ago • 4 comments

[REQUIRED] Environment info

firebase-tools: 13.29.1 Platform: macOS

[REQUIRED] Test case

import { Response } from "express";
import * as functions from "firebase-functions/v2";
import { firestore } from "firebase-admin";
import { FieldPath, FieldValue } from "firebase-admin/firestore";
import * as admin from "firebase-admin";

export const defaultApp = admin.initializeApp();

defaultApp;

export const setUpUsers = functions.https.onRequest(handler(async () => {
    await firestore().collection("users").doc("user1").set({
        field: {
            deep: FieldValue.vector([1.0, 2.0]),
        },
        fieldShallow: FieldValue.vector([1.0, 2.0]),
    });

    return 'Set user';
}));

export const search = functions.https.onRequest(handler(async () => {
    return {
        deepField: await searchForUsers('field.deep'),
        deepFieldDirect: await searchForUsers(new FieldPath('field', 'deep')),
        shallowField: await searchForUsers('fieldShallow'),
    };
}));

async function searchForUsers(path: FieldPath | string): Promise<number> {
    const results = await firestore().collection("users").findNearest({
        distanceMeasure: "EUCLIDEAN",
        queryVector: FieldValue.vector([1.0, 2.0]),
        limit: 10,
        vectorField: path,
    }).get();

    return results.size;
}

function handler(
    callback: () => Promise<any>
): (request: functions.https.Request, response: Response) => Promise<void> {
    return async (_, response) => {
        try {
            const result = await callback();
            response.json({ result });
            response.end();
        } catch (error) {
            console.log(error);
            response.status(500);
            response.end();
        }

    };
}
{
  "name": "functions",
  "scripts": {
    "build": "tsc",
    "build:watch": "tsc --watch",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "20"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "^13.0.0",
    "firebase-functions": "^6.0.1"
  },
  "devDependencies": {
    "typescript": "^5.0.0"
  },
  "private": true
}

[REQUIRED] Steps to reproduce

  1. Set up project through firebase init
  2. Install emulators, functions and firestore
  3. Run firebase emulators:start --project demo-project
  4. Run http://127.0.0.1:5001/demo-project/us-central1/setUpUsers in browser
  5. Run http://127.0.0.1:5001/demo-project/us-central1/search

[REQUIRED] Expected behavior

The expected output of the function is:

{
    "result": {
        "deepField": 1,
        "deepFieldDirect": 1,
        "shallowField": 1
    }
}

(This is the output produced when running against the live instance.)

[REQUIRED] Actual behavior

The output of the function is:

{
    "result": {
        "deepField": 0,
        "deepFieldDirect": 0,
        "shallowField": 1
    }
}

It seems the emulator doesn't handle nested vector fields.

jellynoone avatar Dec 21 '24 17:12 jellynoone

There was an issue with nested vector fields, before https://github.com/googleapis/nodejs-firestore/issues/2081 Linking in case it helps.

jellynoone avatar Dec 21 '24 17:12 jellynoone

Thanks for the detailed report @jellynoone! I'm able to reproduce this issue. As you mentioned, when connecting to the emulator, http://127.0.0.1:5001/demo-project/us-central1/search outputs:

{
  "result": {
    "deepField": 0,
    "deepFieldDirect": 0,
    "shallowField": 1
  }
}

But when connecting to an actual project, the outputs becomes:

{
  "result": {
    "deepField": 1,
    "deepFieldDirect": 1,
    "shallowField": 1
  }
}

I'll mark this as reproducible and raise it to our engineering so they can take a look. Sharing this mcve created using the provided info.

aalej avatar Jan 07 '25 18:01 aalej

Has any progress been made on this?

jellynoone avatar Mar 18 '25 11:03 jellynoone

Any update on this? Would be nice to have it fixed.

sumeetbajra avatar May 21 '25 12:05 sumeetbajra