Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[firestore-emulator: datastore-mode] Unexpected response from query filter on nested property in array #7677

Open
boris-hocde opened this issue Sep 18, 2024 · 1 comment

Comments

@boris-hocde
Copy link

[REQUIRED] Environment info

gcloud: v493.0.0

Platform: Ubuntu

[REQUIRED] Test case

package.json

{
  "version": "1.0.0",
  "description": "",
  "main": "lib/index.js",
  "scripts": {
    "build": "tsc",
    "start": "DATASTORE_EMULATOR_HOST=127.0.0.1:8080 node lib/index.js",
    "start:emulator:old": "gcloud --project=dummy-project-id beta emulators datastore start --use-firestore-in-datastore-mode --host-port=127.0.0.1:8080",
    "start:emulator:new": "gcloud emulators firestore start --database-mode=datastore-mode --host-port=127.0.0.1:8080"
  },
  "devDependencies": {
    "@google-cloud/datastore": "^9.1.0",
    "typescript": "^5.4.3"
  }
}

src/index.ts

import {and, Datastore, PropertyFilter} from "@google-cloud/datastore";

const datastore = new Datastore({
  projectId: "dummy-project-id",
});

const KIND_USER = 'User'

type User = {
  email: string
  fields : {
    key: string,
    value: string,
  }[]
}

export async function getUsersByName(name: string) {
  const query = datastore.createQuery(KIND_USER).filter(and([
    new PropertyFilter('fields.key','=','name'),
    new PropertyFilter('fields.value','=',name),
  ]));
  const [entities] = await datastore.runQuery(query);
  return entities
}

export async function addUser(data: User) {
  const key = datastore.key(KIND_USER);
  const entity = {
    key: key,
    data,
  };
  await datastore.save(entity);
}

async function main() {
  await addUser({email: "foo@example.com", fields: [{key: "name", value: "Awesome Name"}]})

  const users = await getUsersByName("Awesome Name");
  console.log(users);
}

main();

tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "lib"
  },
  "include": ["src"],
  "exclude": []
}

[REQUIRED] Steps to reproduce

Datastore Emulator (Old)

npm install
npm run start:emulator:old
$ npm run build && npm run start

> build
> tsc

> start
> DATASTORE_EMULATOR_HOST=127.0.0.1:8080 node lib/index.js

[
  {
    fields: [ [Object] ],
    email: 'foo@example.com',
    [Symbol(KEY)]: Key {
      namespace: undefined,
      id: '1',
      kind: 'User',
      path: [Getter]
    }
  },
]

Firestore Emulator (New, Preview)

npm install
npm run start:emulator:new
$ npm run build && npm run start

> build
> tsc

> start
> DATASTORE_EMULATOR_HOST=127.0.0.1:8080 node lib/index.js

[]

[REQUIRED] Expected behavior

[
  {
    fields: [ [Object] ],
    email: 'foo@example.com',
    [Symbol(KEY)]: Key {
      namespace: undefined,
      id: '1',
      kind: 'User',
      path: [Getter]
    }
  },
]

[REQUIRED] Actual behavior

The result filtered by fields.name and fields.value should include the user, but not when using the new emulator.

[]

This issue slightly differs from #6999, as the fields property is an array here.

@aalej
Copy link
Contributor

aalej commented Sep 20, 2024

Hey @boris-hocde, thanks for creating a detailed report! I'm able to reproduce the issue using the code snippets and steps provided. I’ll mark this as reproducible and raise this to our engineering team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants