Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Firestore のクエリと全文検索

Ebb5511374cdb5d46e5587608a899284?s=47 miup
August 07, 2018

Firestore のクエリと全文検索

Firebase Meetup #5

Ebb5511374cdb5d46e5587608a899284?s=128

miup

August 07, 2018
Tweet

Transcript

  1. Cookpad Inc. Firestore ͷΫΤϦͱશจݕࡧ ࡾӜ࿨໵

  2. Cookpad Inc. All Rights Reserved. ࣗݾ঺հ w໊લࡾӜ࿨໵ wܦྺ wCookpad 17৽ଔ

    (Komerco ࣄۀ෦  wiOSྺ໿5೥ Firebase ྺ1೥ͪΐͬͱ wTwitter: __miup (ΞϯμʔείΞ2ຊʂ  wGithub: miuP
  3. Cookpad Inc. All Rights Reserved. ࠓ೔࿩͢͜ͱ wFirestore ͷΫΤϦͰͰ͖Δ͜ͱ wFirestore ͷΫΤϦͰͰ͖ͳ͍͜ͱ

    wղܾࡦ
  4. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ wsort worderBy wwhere

    wisEqualTo wisLessThan (orEqualTo) wisGreaterThan (orEqualTo)
  5. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ wpaging wlimit wstartAfter,

    endBefore (order ͍ͯ͠Δ஋, DocumentReference) wetc…
  6. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ 1ճͷΫΤϦͰ isLessThan ͱ

    isGreaterThan ͸ 1ͭͷ Field ʹର͔ͯ͠͠࢖͑ͳ͍ʂ ͨͩ͠ʂ
 ੍໿͕͋Δ
  7. interface Product { name: string // ঎඼໊ price: number //

    Ձ֨ stock: number // ࡏݿ isActive: boolean // ࿦ཧ࡟আ createdAt: firestore.Timestamp updatedAt: firestore.Timestamp }
  8. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ w୯ҰͷϑΟʔϧυʹର͢Δෳ਺ͷൣғൺֱ wෳ਺ͷϑΟʔϧυʹର͢Δ౳Ձԋࢉࢠ wެ։தͷ5000ԁ~10000ԁͷࡏݿͷlͳ͍z঎඼Λऔಘ

  9. 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 => { ... }) })
  10. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖Δ͜ͱ wෳ਺ͷϑΟʔϧυʹ·͕ͨΔΫΤϦ wΧελϜΠϯσοΫε͕ඞཁ ෳ߹ΠϯσοΫεΈ͍ͨͳ΋ͷʣ

    wΫΤϦ౤͛ͯΤϥʔ͕ฦͬͯ͘Δͱ URL ͕ॻ͍ͯ͋ΔͷͰͦ͜ Λ౿Ί͹؆୯ʹઃఆͰ͖Δ
  11. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖ͳ͍͜ͱ wશจݕࡧ -*,&΋ 

    wisNotEqualTo (݁ߏͭΒ͍) wෳ਺ͷϑΟʔϧυʹର͢Δൣғൺֱ wެ։தͷ5000ԁ~10000ԁͷࡏݿͷl͋Δz঎඼Λऔಘ
  12. 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 => { ... }) }) ❌
  13. 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 => { ... }) }) ❌
  14. Cookpad Inc. All Rights Reserved. Firestore ͷΫΤϦͰͰ͖ͳ͍͜ͱ wެ։தͷ5000ԁ~10000ԁͷࡏݿͷl͋Δz঎඼Λऔಘ͕Ͱ͖ͳ͍ wશจݕࡧ͕Ͱ͖ͳ͍ ݁ߏݫ͍͠

  15. Cookpad Inc. All Rights Reserved. Ͳ͏͢Ε͹ʜ

  16. Cookpad Inc. All Rights Reserved. Algolia 4BB4ʹཔΖ͏ શจݕࡧʢincremental search) Λఏڙ͍ͯ͠Δ

    SaaS iOS, Android, Web Ͱ SDK ఏڙ͞Ε͍ͯΔ ʢଞʹ΋ݕࡧ4BB4͋Δ͚Ͳެࣜʹ΋໊લ͕ग़͍ͯΔͷͰ"MHPMJBΛ঺հ͠·͢ʣ
  17. Cookpad Inc. All Rights Reserved. ྲྀΕ Cloud Firestore Cloud Functions

    Algolia Save Document Event trigger Algolia API Search
  18. 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) } }) }) })
  19. Cookpad Inc. All Rights Reserved. ྲྀΕ Cloud Firestore Cloud Functions

    Algolia Save Document Event trigger Algolia API Search
  20. Cookpad Inc. All Rights Reserved. ܕ͕ͳ͍ Algolia ݕࡧ݁Ռʹܕ͕ͳ͍
 Swift Ͱॻ͘ͳΒܕ͕ཉ͍͠


    Kotlin Ͱ΋ Java Ͱ΋ TypeScript Ͱ΋ಉ͚ͩ͡Ͳ
  21. Cookpad Inc. All Rights Reserved. ϥΠϒϥϦ࡞ͬͨ

  22. Cookpad Inc. All Rights Reserved. Algent Type Safe Algolia Search

    Client for Swift
 https://github.com/miuP/Algent
  23. Cookpad Inc. All Rights Reserved. ࢖͍ํ wσʔλͷܕΛ࡞Δ wRequest Λ࡞Δ w౤͛Δ

  24. struct User: Decodable { let objectID: String let name: String

    let bio: String let isActive: Bool let followerCount: Int let followeeCount: Int let _tags: [String] }
  25. 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 } }
  26. 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) } }
  27. Cookpad Inc. All Rights Reserved. ·ͱΊ wFirestore ͰͷΫΤϦ wൣғࢦఆΛҟͳΔFieldʹ͔͚ΒΕͳ͍ wisNotEqualTo

    ͕ͳ͍ wLIKEͱ͔શจݕࡧ͕Ͱ͖ͳ͍ wAlgolia w֎෦αʔϏεʹͳΔͷͰ࿈ܞ͕ඞཁ(Firebase ͷ༗ྉϓϥϯඞཁ) wAlgent ࢖ͬͯΈ͍ͯͩ͘͞