1. 概要
Cloud Firestoreのデータを抽出してみます。
2. プロジェクトを作成
こちらを参考
3. Firestoreのセットアップ
こちらを参考
4. プロジェクトのロケーションを変更
こちらを参考
5. Functionsのセットアップ
こちらを参考
6. ソースコード
6-1. functions/src/common.ts
import * as functions from "firebase-functions";
export const f = functions.region("asia-northeast1");
6-2. functions/src/database.ts
import * as admin from "firebase-admin";
admin.initializeApp();
export const db = () => admin.firestore();
6-3. functions/src/types.ts
import * as admin from "firebase-admin";
export type Timestamp = admin.firestore.Timestamp | admin.firestore.FieldValue;
6-4. functions/src/models.ts
import * as types from "./types";
export type RequestCity = {
name: string,
state: string,
country: string,
capital: boolean,
population: number,
regions: string[],
updatedAt: types.Timestamp,
createdAt: types.Timestamp
}
6-5. functions/src/utils.ts
import * as firestore from "firebase-admin/firestore";
export const serverTimestamp = () => firestore.FieldValue.serverTimestamp();
6-6. functions/src/simple_query.ts
import * as database from "./database";
import * as common from "./common";
export const getSimpleQuery01 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('state', '==', 'CA').get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery02 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('capital', '==', true).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery03 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('population', '<', 1000000).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery04 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('name', '>=', 'San Francisco').get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery05 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('capital', '!=', false).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery06 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('regions', 'array-contains', 'west_coast').get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery07 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('country', 'in', ['USA', 'Japan']).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery08 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('country', 'not-in', ['USA', 'Japan']).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery09 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('regions', 'array-contains-any', ['west_coast', 'east_coast']).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery10 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('regions', 'in', [['west_coast', 'east_coast']]).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery11 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('regions', 'in', [['west_coast', 'socal']]).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getSimpleQuery12 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('regions', 'in', [['socal', 'west_coast']]).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
6-7. functions/src/composite_query.ts
import * as database from "./database";
import * as common from "./common";
export const getCompositeQuery01 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('state', '==', 'CA').where('name', '==', 'San Diego').get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getCompositeQuery02 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('state', '==', 'CA').where('population', '<', 1000000).get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
export const getCompositeQuery03 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const citiesRef = database.db().collection(collectionId);
const allCaRes = await citiesRef.where('state', '>=', 'CA').where('state', '<=', 'IN').get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
6-8. functions/src/group_query.ts
import * as database from "./database";
import * as common from "./common";
export const getCollectionGroupQuery01 = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const allCaRes = await database.db().collectionGroup('landmarks').where('type', '==', 'museum').get().then(async (snapshot) => snapshot.docs.map((v) => v.data()));
response.status(200).send(allCaRes);
});
6-9. functions/src/index.ts
import * as database from "./database";
import * as common from "./common";
import * as models from "./models";
import * as utils from "./utils";
export * as simple_query from "./simple_query";
export * as composite_query from "./composite_query";
export * as group_query from "./group_query";
export const addData = common.f.https.onRequest(async (request, response) => {
if (request.method !== 'POST') {
response.status(405).send('Please request as a POST!');
return;
}
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const docId = request.query.docId !== undefined ? request.query.docId.toString() : "";
const requestCity : models.RequestCity = request.body;
requestCity.updatedAt = utils.serverTimestamp();
requestCity.createdAt = utils.serverTimestamp();
try {
await database.db().collection(collectionId).doc(docId).set(requestCity);
} catch (e) {
console.error(e);
response.status(500).send(e);
}
response.status(200).send("OK");
});
export const addSubData = common.f.https.onRequest(async (request, response) => {
const collectionId = request.get('X-CollectionId');
if (collectionId === undefined) {
response.status(400).send('Please request with a Collection Id');
return;
}
const subCollectionId = 'landmarks';
try {
await database.db().collection(collectionId).doc('SF').collection(subCollectionId).doc().set({'name': 'Golden Gate Bridge','type': 'bridge','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('SF').collection(subCollectionId).doc().set({'name': 'Legion of Honor','type': 'museum','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('LA').collection(subCollectionId).doc().set({'name': 'Griffith Park','type': 'park','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('LA').collection(subCollectionId).doc().set({'name': 'The Getty','type': 'museum','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('DC').collection(subCollectionId).doc().set({'name': 'Lincoln Memorial','type': 'memorial','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('DC').collection(subCollectionId).doc().set({'name': 'National Air and Space Museum','type': 'museum','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('TOK').collection(subCollectionId).doc().set({'name': 'Ueno Park','type': 'park','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('TOK').collection(subCollectionId).doc().set({'name': 'National Museum of Nature and Science','type': 'museum','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('BJ').collection(subCollectionId).doc().set({'name': 'Jingshan Park','type': 'park','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
await database.db().collection(collectionId).doc('BJ').collection(subCollectionId).doc().set({'name': 'Beijing Ancient Observatory','type': 'museum','updatedAt': utils.serverTimestamp(),'createdAt': utils.serverTimestamp()});
} catch (e) {
console.error(e);
response.status(500).send(e);
}
response.status(200).send("OK");
});
7. エミュレータ スイートのセットアップ
7-1. 初期化
7-2. functions/package.json
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"build:watch": "tsc --watch",
"serve": "npm run build && firebase emulators:start",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "18"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2",
"eslint": "^8.32.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.27.5",
"firebase-functions-test": "^3.0.0",
"typescript": "^4.9.4"
},
"private": true
}
7-3. エミュレータを起動
cd functions
npm run serve
> serve
> npm run build && firebase emulators:start
> build
> tsc
i emulators: Starting emulators: functions, firestore, storage
⚠ functions: The following emulators are not running, calls to these services from the Functions emulator will affect production: auth, database, hosting, pubsub
✔ functions: Using node@18 from host.
i firestore: Firestore Emulator logging to firestore-debug.log
✔ firestore: Firestore Emulator UI websocket is running on 9150.
i ui: Emulator UI logging to ui-debug.log
i functions: Watching "/home/sondon/dev/wsl/gcp/firebase/sample003/functions" for Cloud Functions...
⚠ functions: package.json indicates an outdated version of firebase-functions. Please upgrade using npm install --save firebase-functions@latest in your functions directory.
✔ functions: Loaded functions definitions from source: simple_query.getSimpleQuery01, simple_query.getSimpleQuery02, simple_query.getSimpleQuery03, simple_query.getSimpleQuery04, simple_query.getSimpleQuery05, simple_query.getSimpleQuery06, simple_query.getSimpleQuery07, simple_query.getSimpleQuery08, simple_query.getSimpleQuery09, simple_query.getSimpleQuery10, simple_query.getSimpleQuery11, simple_query.getSimpleQuery12, composite_query.getCompositeQuery01, composite_query.getCompositeQuery02, composite_query.getCompositeQuery03, group_query.getCollectionGroupQuery01, addData, addSubData.
✔ functions[asia-northeast1-simple_query-getSimpleQuery01]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery01).
✔ functions[asia-northeast1-simple_query-getSimpleQuery02]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery02).
✔ functions[asia-northeast1-simple_query-getSimpleQuery03]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery03).
✔ functions[asia-northeast1-simple_query-getSimpleQuery04]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery04).
✔ functions[asia-northeast1-simple_query-getSimpleQuery05]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery05).
✔ functions[asia-northeast1-simple_query-getSimpleQuery06]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery06).
✔ functions[asia-northeast1-simple_query-getSimpleQuery07]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery07).
✔ functions[asia-northeast1-simple_query-getSimpleQuery08]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery08).
✔ functions[asia-northeast1-simple_query-getSimpleQuery09]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery09).
✔ functions[asia-northeast1-simple_query-getSimpleQuery10]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery10).
✔ functions[asia-northeast1-simple_query-getSimpleQuery11]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery11).
✔ functions[asia-northeast1-simple_query-getSimpleQuery12]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery12).
✔ functions[asia-northeast1-composite_query-getCompositeQuery01]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/composite_query-getCompositeQuery01).
✔ functions[asia-northeast1-composite_query-getCompositeQuery02]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/composite_query-getCompositeQuery02).
✔ functions[asia-northeast1-composite_query-getCompositeQuery03]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/composite_query-getCompositeQuery03).
✔ functions[asia-northeast1-group_query-getCollectionGroupQuery01]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/group_query-getCollectionGroupQuery01).
✔ functions[asia-northeast1-addData]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addData).
✔ functions[asia-northeast1-addSubData]: http function initialized (http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addSubData).
┌─────────────────────────────────────────────────────────────┐
│ ✔ All emulators ready! It is now safe to connect your app. │
│ i View Emulator UI at http://127.0.0.1:4000/ │
└─────────────────────────────────────────────────────────────┘
┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator │ Host:Port │ View in Emulator UI │
├───────────┼────────────────┼─────────────────────────────────┤
│ Functions │ 127.0.0.1:5001 │ http://127.0.0.1:4000/functions │
├───────────┼────────────────┼─────────────────────────────────┤
│ Firestore │ 127.0.0.1:8080 │ http://127.0.0.1:4000/firestore │
├───────────┼────────────────┼─────────────────────────────────┤
│ Storage │ 127.0.0.1:9199 │ http://127.0.0.1:4000/storage │
└───────────┴────────────────┴─────────────────────────────────┘
Emulator Hub running at 127.0.0.1:4400
Other reserved ports: 4500, 9150
Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
8. データの登録
8-1. 登録
curl -X POST -H "Content-Type: application/json" -H "X-CollectionId:cities" -d '{"name":"San Francisco","state":"CA","country":"USA","capital":false,"population":860000,"regions":["west_coast","norcal"]}' http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addData?docId=SF
curl -X POST -H "Content-Type: application/json" -H "X-CollectionId:cities" -d '{"name":"Los Angeles","state":"CA","country":"USA","capital":false,"population":3900000,"regions":["west_coast","socal"]}' http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addData?docId=LA
curl -X POST -H "Content-Type: application/json" -H "X-CollectionId:cities" -d '{"name":"Washington, D.C.","state":null,"country":"USA","capital":true,"population":680000,"regions":["east_coast"]}' http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addData?docId=DC
curl -X POST -H "Content-Type: application/json" -H "X-CollectionId:cities" -d '{"name":"Tokyo","state":null,"country":"Japan","capital":true,"population":9000000,"regions":["kanto","honshu"]}' http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addData?docId=TOK
curl -X POST -H "Content-Type: application/json" -H "X-CollectionId:cities" -d '{"name":"Beijing","state":null,"country":"China","capital":true,"population":21500000,"regions":["jingjinji","hebei"]}' http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addData?docId=BJ
8-2. 登録(サブコレクション)
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/addSubData
8-3. 登録データ
№ | Collection | Document | Data or Collection | Document | Data |
---|---|---|---|---|---|
1 | cities | SF | { “name”: “San Francisco”, “state”: “CA”, “country”: “USA”, “capital”: false, “population”: 860000, “regions”: [ “west_coast”, “norcal” ] } | ||
2 | landmarks | AUTO | { name: ‘Golden Gate Bridge’, type: ‘bridge’ } | ||
3 | landmarks | AUTO | { name: ‘Legion of Honor’, type: ‘museum’ } | ||
4 | LA | { “name”: “Los Angeles”, “state”: “CA”, “country”: “USA”, “capital”: false, “population”: 3900000, “regions”: [ “west_coast”, “socal” ] } | |||
5 | landmarks | AUTO | { name: ‘Griffith Park’, type: ‘park’ } | ||
6 | landmarks | AUTO | { name: ‘The Getty’, type: ‘museum’ } | ||
7 | DC | { “name”: “Washington, D.C.”, “state”: null, “country”: “USA”, “capital”: true, “population”: 680000, “regions”: [ “east_coast” ] } | |||
8 | landmarks | AUTO | { name: ‘Lincoln Memorial’, type: ‘memorial’ } | ||
9 | landmarks | AUTO | { name: ‘National Air and Space Museum’, type: ‘museum’ } | ||
10 | TOK | { “name”: “Tokyo”, “state”: null, “country”: “Japan”, “capital”: true, “population”: 9000000, “regions”: [ “kanto”, “honshu” ] } | |||
11 | landmarks | AUTO | { name: ‘Ueno Park’, type: ‘park’ } | ||
12 | landmarks | AUTO | { name: ‘National Museum of Nature and Science’, type: ‘museum’ } | ||
13 | BJ | { “name”: “Beijing”, “state”: null, “country”: “China”, “capital”: true, “population”: 21500000, “regions”: [ “jingjinji”, “hebei” ] } | |||
14 | landmarks | AUTO | { name: ‘Jingshan Park’, type: ‘park’ } | ||
15 | landmarks | AUTO | { name: ‘Beijing Ancient Observatory’, type: ‘museum’ } |
9. 単純なクエリ
9-1. stateがCAのすべての都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery01
[
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"socal"
],
"name": "Los Angeles",
"state": "CA",
"population": 3900000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
}
]
9-2. すべての首都を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery02
[
{
"country": "China",
"capital": true,
"regions": [
"jingjinji",
"hebei"
],
"name": "Beijing",
"state": null,
"population": 21500000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 875000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 875000000
}
},
{
"country": "USA",
"capital": true,
"regions": [
"east_coast"
],
"name": "Washington, D.C.",
"state": null,
"population": 680000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
}
},
{
"country": "Japan",
"capital": true,
"regions": [
"kanto",
"honshu"
],
"name": "Tokyo",
"state": null,
"population": 9000000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
}
}
]
9-3. 人口数が100万未満を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery03
[
{
"country": "USA",
"capital": true,
"regions": [
"east_coast"
],
"name": "Washington, D.C.",
"state": null,
"population": 680000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
}
]
9-4. nameがSan Franciscoより大きいデータを返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery04
[
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
},
{
"country": "Japan",
"capital": true,
"regions": [
"kanto",
"honshu"
],
"name": "Tokyo",
"state": null,
"population": 9000000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
}
},
{
"country": "USA",
"capital": true,
"regions": [
"east_coast"
],
"name": "Washington, D.C.",
"state": null,
"population": 680000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
}
}
]
9-5. 首都じゃなくない都市(=首都)を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery05
[
{
"country": "China",
"capital": true,
"regions": [
"jingjinji",
"hebei"
],
"name": "Beijing",
"state": null,
"population": 21500000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 875000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 875000000
}
},
{
"country": "USA",
"capital": true,
"regions": [
"east_coast"
],
"name": "Washington, D.C.",
"state": null,
"population": 680000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
}
},
{
"country": "Japan",
"capital": true,
"regions": [
"kanto",
"honshu"
],
"name": "Tokyo",
"state": null,
"population": 9000000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
}
}
]
9-6. regionsがwest_coastの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery06
[
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"socal"
],
"name": "Los Angeles",
"state": "CA",
"population": 3900000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
}
]
9-7. 国がUSAとJapanの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery07
[
{
"country": "USA",
"capital": true,
"regions": [
"east_coast"
],
"name": "Washington, D.C.",
"state": null,
"population": 680000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"socal"
],
"name": "Los Angeles",
"state": "CA",
"population": 3900000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
},
{
"country": "Japan",
"capital": true,
"regions": [
"kanto",
"honshu"
],
"name": "Tokyo",
"state": null,
"population": 9000000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 796000000
}
}
]
9-8. 国がUSAとJapanじゃない都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery08
[
{
"country": "China",
"capital": true,
"regions": [
"jingjinji",
"hebei"
],
"name": "Beijing",
"state": null,
"population": 21500000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 875000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 875000000
}
}
]
9-9. regionsがwest_coastかeast_coastの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery09
[
{
"country": "USA",
"capital": true,
"regions": [
"east_coast"
],
"name": "Washington, D.C.",
"state": null,
"population": 680000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 722000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"socal"
],
"name": "Los Angeles",
"state": "CA",
"population": 3900000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
}
]
9-10. regionsがwest_coast且つeast_coastの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery10
[]
9-11. regionsがwest_coast且つsocalの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery11
[
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"socal"
],
"name": "Los Angeles",
"state": "CA",
"population": 3900000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
}
}
]
- 「in」は、「array-contains-any」とは異なり、句は配列の長さ、順序、および値が完全に一致する場合に一致する
9-12. regionsがsocal且つwest_coastの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/simple_query-getSimpleQuery12
[]
10. 複合クエリ
10-1. stateがCA且つnameがSan Diegoの都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/composite_query-getCompositeQuery01
[]
10-2. stateがCA且つ人口数が100万未満の都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/composite_query-getCompositeQuery02
[
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
}
]
10-3. stateがCA以上かつstateがIN以下の都市を返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/composite_query-getCompositeQuery03
[
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"socal"
],
"name": "Los Angeles",
"state": "CA",
"population": 3900000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 645000000
}
},
{
"country": "USA",
"capital": false,
"regions": [
"west_coast",
"norcal"
],
"name": "San Francisco",
"state": "CA",
"population": 860000,
"createdAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
},
"updatedAt": {
"_seconds": 1675484699,
"_nanoseconds": 472000000
}
}
]
※異なるフィールドの範囲フィルターはNG
citiesRef.where('state', '>=', 'CA').where('population', '>', 1000000); // NG
11. コレクション グループ クエリ
11-1. すべての都市のすべてのmuseumのランドマークを返す
curl -H "X-CollectionId:cities" http://127.0.0.1:5001/isub-sample-003/asia-northeast1/group_query-getCollectionGroupQuery01
[
{
"name": "Beijing Ancient Observatory",
"type": "museum",
"createdAt": {
"_seconds": 1675484747,
"_nanoseconds": 242000000
},
"updatedAt": {
"_seconds": 1675484747,
"_nanoseconds": 242000000
}
},
{
"name": "National Air and Space Museum",
"type": "museum",
"createdAt": {
"_seconds": 1675484747,
"_nanoseconds": 207000000
},
"updatedAt": {
"_seconds": 1675484747,
"_nanoseconds": 207000000
}
},
{
"name": "The Getty",
"type": "museum",
"createdAt": {
"_seconds": 1675484747,
"_nanoseconds": 192000000
},
"updatedAt": {
"_seconds": 1675484747,
"_nanoseconds": 192000000
}
},
{
"name": "Legion of Honor",
"type": "museum",
"createdAt": {
"_seconds": 1675484747,
"_nanoseconds": 167000000
},
"updatedAt": {
"_seconds": 1675484747,
"_nanoseconds": 167000000
}
},
{
"name": "National Museum of Nature and Science",
"type": "museum",
"createdAt": {
"_seconds": 1675484747,
"_nanoseconds": 219000000
},
"updatedAt": {
"_seconds": 1675484747,
"_nanoseconds": 219000000
}
}
]
12. 備考
- クエリ演算子
- クエリの制限
13. 参考
投稿者プロフィール
-
開発好きなシステムエンジニアです。
卓球にハマってます。