firebase-tools
firebase-tools copied to clipboard
[firestore-emulator: datastore-mode] Unexpected response from query filter on nested property in array
[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: "[email protected]", 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: '[email protected]',
[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: '[email protected]',
[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 https://github.com/firebase/firebase-tools/issues/6999, as the fields property is an array here.
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.