Skip to content

Instantly share code, notes, and snippets.

@jaonoctus
Last active September 6, 2018 03:07
Show Gist options
  • Save jaonoctus/b4efdc996413f42b7e070422f5541704 to your computer and use it in GitHub Desktop.
Save jaonoctus/b4efdc996413f42b7e070422f5541704 to your computer and use it in GitHub Desktop.
firestore inequality query workaround
import { firestore } from 'firebase-admin'
import { https, Request, Response } from 'firebase-functions'
import * as express from 'express'
const app = express()
app.get('/:id', async (req: Request, res: Response) => {
const accountId = req.params.id
const articlesQuery = await firestore()
.collection('articles')
.where('notUsedBy', 'array-contains', accountId)
.where('lockedAt', '==', null)
.get()
// TODO: lock files after query (transaction)
const articles = articlesQuery.docs.map((snap: firestore.DocumentSnapshot) => ({id: snap.id, ...snap.data() }))
res.json(articles)
})
export default https.onRequest(app)
export const MAX_BATCH_SIZE = 500
import { initializeApp } from 'firebase-admin'
initializeApp()
export { default as Indexes } from './indexes'
export { default as onCreateArticle } from './onCreateArticle'
export { default as onCreateAccount } from './onCreateAccount'
export { default as availableArticles } from './availableArticles'
import { firestore } from 'firebase-functions'
import { firestore as db } from 'firebase-admin'
const path = collectionPath => `${collectionPath}/{id}`
const indexDocRef = documentPath => db().collection('indexes').doc(documentPath)
const onCreate = (collection: string) => {
return firestore.document(path(collection)).onCreate((snap: firestore.DocumentSnapshot) => {
return indexDocRef(collection).update({ docs: db.FieldValue.arrayUnion(snap.id) })
})
}
const onDelete = (collection: string) => {
return firestore.document(path(collection)).onDelete((snap: firestore.DocumentSnapshot) => {
return indexDocRef(collection).update({ docs: db.FieldValue.arrayRemove(snap.id) })
})
}
const onCreateAccount = onCreate('accounts')
const onDeleteAccount = onDelete('accounts')
const onCreateArticle = onCreate('articles')
const onDeleteArticle = onDelete('articles')
export default {
onCreateAccount,
onDeleteAccount,
onCreateArticle,
onDeleteArticle
}
import { chunk } from 'lodash'
import { firestore } from 'firebase-functions'
import { firestore as db } from 'firebase-admin'
import { MAX_BATCH_SIZE } from './constants'
const articlesIndexes = db().collection('indexes').doc('articles')
export default firestore.document('accounts/{id}').onCreate(async (accountSnapshot: firestore.DocumentSnapshot) => {
const articleKeys = (await articlesIndexes.get()).data().docs as string[]
const batches = chunk(articleKeys, MAX_BATCH_SIZE).map(keys => {
const batch = db().batch()
keys.forEach(key => {
const articleRef = db().collection('articles').doc(key)
batch.update(articleRef, {
notUsedBy: db.FieldValue.arrayUnion(accountSnapshot.id)
})
})
return batch.commit()
})
return Promise.all(batches)
})
import { firestore } from 'firebase-functions'
import { firestore as db } from 'firebase-admin'
const accountsIndex = db().collection('indexes').doc('accounts')
export default firestore.document('articles/{id}').onCreate((articleSnapshot: firestore.DocumentSnapshot) => {
return db().runTransaction(transaction => {
return transaction.get(accountsIndex).then(indexSnap => {
const { docs } = indexSnap.data()
return articleSnapshot.ref.update({
notUsedBy: docs,
usedBy: [],
lockedAt: null
})
})
})
})
@jaonoctus
Copy link
Author

jaonoctus commented Sep 6, 2018

available

where('notUsedBy', 'array-contains', userId).where('lockedAt', '==', null)
// or
where('notUsedBy', 'array-contains', userId).where('lockedAt', '<=', new Date())

approved

.where('approvedBy', 'array-contains', usedId)

disapproved

.where('disapprovedBy', 'array-contains', usedId)

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