Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Firestore のクエリと全文検索
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
miup
August 07, 2018
Programming
3.6k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Firestore のクエリと全文検索
Firebase Meetup #5
miup
August 07, 2018
More Decks by miup
See All by miup
Algolia with Firebase
miup
2
1.5k
Firestore, Cloud Storage を用いた アプリ内での画像の扱い方
miup
5
25k
Firebase Cloud Messaging 入門編
miup
0
5.2k
The way of truly serverless application
miup
1
4.6k
Other Decks in Programming
See All in Programming
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
550
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
400
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
850
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
710
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
590
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
6.8k
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
540
RTSPクライアントを自作してみた話
simotin13
0
610
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
270
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
290
AI時代のUIはどこへ行く?その2!
yusukebe
22
7.4k
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
430
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
220
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
210
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Balancing Empowerment & Direction
lara
6
1.2k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
200
A Soul's Torment
seathinner
6
3k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
560
RailsConf 2023
tenderlove
30
1.5k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
600
Technical Leadership for Architectural Decision Making
baasie
3
420
Transcript
Cookpad Inc. Firestore ͷΫΤϦͱશจݕࡧ ࡾӜ
Cookpad Inc. All Rights Reserved. ࣗݾհ w໊લࡾӜ wܦྺ wCookpad 17৽ଔ
(Komerco ࣄۀ෦ wiOSྺ5 Firebase ྺ1ͪΐͬͱ wTwitter: __miup (ΞϯμʔείΞ2ຊʂ wGithub: miuP
Cookpad Inc. All Rights Reserved. ࠓ͢͜ͱ wFirestore ͷΫΤϦͰͰ͖Δ͜ͱ wFirestore ͷΫΤϦͰͰ͖ͳ͍͜ͱ
wղܾࡦ
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ wsort worderBy wwhere
wisEqualTo wisLessThan (orEqualTo) wisGreaterThan (orEqualTo)
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ wpaging wlimit wstartAfter,
endBefore (order ͍ͯ͠Δ, DocumentReference) wetc…
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ 1ճͷΫΤϦͰ isLessThan ͱ
isGreaterThan 1ͭͷ Field ʹର͔ͯ͑͠͠ͳ͍ʂ ͨͩ͠ʂ ੍͕͋Δ
interface Product { name: string // ໊ price: number //
Ձ֨ stock: number // ࡏݿ isActive: boolean // ཧআ createdAt: firestore.Timestamp updatedAt: firestore.Timestamp }
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ w୯ҰͷϑΟʔϧυʹର͢Δෳͷൣғൺֱ wෳͷϑΟʔϧυʹର͢ΔՁԋࢉࢠ wެ։தͷ5000ԁ~10000ԁͷࡏݿͷlͳ͍zΛऔಘ
const products = await admin.firestore().collection('products') .where('isActive', '==', true) .where(‘stock', '==',
0) .where('price', '<=', 10000) .where('price', ‘>=', 5000) .then(querySnapshot => { return querySnapshot.docs.map(doc => { ... }) })
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ wෳͷϑΟʔϧυʹ·͕ͨΔΫΤϦ wΧελϜΠϯσοΫε͕ඞཁ ෳ߹ΠϯσοΫεΈ͍ͨͳͷʣ
wΫΤϦ͛ͯΤϥʔ͕ฦͬͯ͘Δͱ URL ͕ॻ͍ͯ͋ΔͷͰͦ͜ Λ౿Ί؆୯ʹઃఆͰ͖Δ
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖ͳ͍͜ͱ wશจݕࡧ -*,&
wisNotEqualTo (݁ߏͭΒ͍) wෳͷϑΟʔϧυʹର͢Δൣғൺֱ wެ։தͷ5000ԁ~10000ԁͷࡏݿͷl͋ΔzΛऔಘ
const products = await admin.firestore().collection('products') .where('isActive', '==', true) .where('stock', '>',
0) .where('price', '<=', 10000) .where('price', ‘>=', 5000) .then(querySnapshot => { return querySnapshot.docs.map(doc => { ... }) }) ❌
const products = await admin.firestore().collection('products') .where('isActive', '==', true) .where('stock', '!=',
0) .where('price', '<=', 10000) .where('price', ‘>=', 5000) .then(querySnapshot => { return querySnapshot.docs.map(doc => { ... }) }) ❌
Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖ͳ͍͜ͱ wެ։தͷ5000ԁ~10000ԁͷࡏݿͷl͋ΔzΛऔಘ͕Ͱ͖ͳ͍ wશจݕࡧ͕Ͱ͖ͳ͍ ݁ߏݫ͍͠
Cookpad Inc. All Rights Reserved. Ͳ͏͢Εʜ
Cookpad Inc. All Rights Reserved. Algolia 4BB4ʹཔΖ͏ શจݕࡧʢincremental search) Λఏڙ͍ͯ͠Δ
SaaS iOS, Android, Web Ͱ SDK ఏڙ͞Ε͍ͯΔ ʢଞʹݕࡧ4BB4͋Δ͚Ͳެࣜʹ໊લ͕ग़͍ͯΔͷͰ"MHPMJBΛհ͠·͢ʣ
Cookpad Inc. All Rights Reserved. ྲྀΕ Cloud Firestore Cloud Functions
Algolia Save Document Event trigger Algolia API Search
algoliasearch(functions.config().algolia.app_id, functions.config().algolia.api_key) const productsIndex = algolia.default.initIndex('products') functions.firestore.document('products/{productID}').onCreate(async (snapshot, context) =>
{ const firProduct = new Tart.Snapshot<Firebase.Product>(snapshot) // আࡁΈͷొ͠ͳ͍ if (!firProduct.data.isActive) { return undefined } // Algolia ʹอଘ͢Δσʔλʹม(Reference Λ ID ʹ͢Δͱ͔͢Δ) const product = new Product(firProduct) return new Promise((resolve, reject) => { productsIndex.addObject(product, async (error, response) => { if (error) { throw error } else { resolve(response) } }) }) })
Cookpad Inc. All Rights Reserved. ྲྀΕ Cloud Firestore Cloud Functions
Algolia Save Document Event trigger Algolia API Search
Cookpad Inc. All Rights Reserved. ܕ͕ͳ͍ Algolia ݕࡧ݁Ռʹܕ͕ͳ͍ Swift Ͱॻ͘ͳΒܕ͕ཉ͍͠
Kotlin Ͱ Java Ͱ TypeScript Ͱಉ͚ͩ͡Ͳ
Cookpad Inc. All Rights Reserved. ϥΠϒϥϦ࡞ͬͨ
Cookpad Inc. All Rights Reserved. Algent Type Safe Algolia Search
Client for Swift https://github.com/miuP/Algent
Cookpad Inc. All Rights Reserved. ͍ํ wσʔλͷܕΛ࡞Δ wRequest Λ࡞Δ w͛Δ
struct User: Decodable { let objectID: String let name: String
let bio: String let isActive: Bool let followerCount: Int let followeeCount: Int let _tags: [String] }
struct SarchUserRequest: AlgoliaRequestProtocol { // set search result type typealias
HitType = User let page: Int let per: Int let text: String? let hashtags: [String]? var indexName: String { return "user" } var query: AlgentQuery { let query = AlgentQuery(query: text) query.page = UInt(page) query.hitsPerPage = UInt(per) if let hashtags = hashtags { query.tagFilters = hashtags } return query } init(page: Int, per: Int, text: String? = nil, hashtags: [String]? = nil) { self.page = page self.per = per self.text = text self.hashtags = hashtags } }
let request = SarchUserRequest(page: 0, per: 20, text: "", hashtags:
[]) Algent.shared.search(request: request) { result in switch result { case .success(let response): // response is AlgoliaResponse<Request.HitType> print(response.hits) // see hit object:[HitType] case .failure( let error): print(error) } }
Cookpad Inc. All Rights Reserved. ·ͱΊ wFirestore ͰͷΫΤϦ wൣғࢦఆΛҟͳΔFieldʹ͔͚ΒΕͳ͍ wisNotEqualTo
͕ͳ͍ wLIKEͱ͔શจݕࡧ͕Ͱ͖ͳ͍ wAlgolia w֎෦αʔϏεʹͳΔͷͰ࿈ܞ͕ඞཁ(Firebase ͷ༗ྉϓϥϯඞཁ) wAlgent ͬͯΈ͍ͯͩ͘͞