LoginSignup
13
10

More than 5 years have passed since last update.

firestoreでタグ検索とか

Last updated at Posted at 2018-02-21

firestoreのwhere句で1時間くらいハマったのでメモ。

TL;DR

firestoreで、全てのcatカテゴリーが登録されてるデータを取得したい場合、カテゴリーObjectにcat: マップ値のデータを登録するが
new Date()ではなくDate.parse(new Date())のように正しくマップ値に変換して登録しないとwhere('categories.cat', '>', 0)は解釈できない。
そりゃそうだ。

公式Doc

cloud firestore: 配列、リスト、セットの操作

// The value of each entry in 'categories' is a unix timestamp
{
  title: "My great post",
  categories: {
    technology: 1502144665,
    opinion: 1502144665,
    cats: 1502144665
  }
}

範囲フィルタを使用して複数のフィールドにクエリを実行するには、複合インデックスが必要です。しかし、上記の手法ではこれが不可能です。インデックスは、特定のフィールドパスに定義する必要があります。したがって、categories.cats や categories.opinion などの可能なフィールドパスごとにインデックスを作成しなければなりませんが、カテゴリがユーザー生成されている場合にはこれを事前に行うことができません。

この制限を回避するには、クエリのすべての情報をマップ値にエンコードします。

有効なクエリ

 db.collection('posts')
    .where('categories.cats', '>', 0)
    .orderBy('categories.cats');
)

上記のようなfirestore設計、
フィールドの値をマップ値にエンコードすることで、categoriesにcatが存在する全てのドキュメントをorderBy込みで取得可能になります。

ハマった点

タイムスタンプ入れとけばいいのか〜と、そのままnew Date()入れていたのでwhere(`members.${userId}`, '>', 0)は解釈できなかった。
new Date()ではなくDate.parse(new Date())を保存が正しい。

sample document (firestore)

スクリーンショット 2018-02-22 2.46.38.png

修正済みコード

// save
export const addSampleCollection = async ({ commit }, { doc }) => {
  const now = new Date()
  let members = {}
  // members[doc.author] = now          // [NG] 2018年2月22~~ (タイムスタンプ)
  members[doc.author] = Date.parse(now) // [OK] 151923~~~
  await docsRef.add({
    author: doc.author,
    members: members,
    release_at: doc.release_at
    title: doc.title,
    create_at: now,
    update_at: now,
  }).then(function () {
    console.log('[success] addDoc')
  }).catch(function (error) {
    console.log('[error] addDoc', error)
  })
}

// get
export const getSampleCollectionDoc = async ({ commit }, { userId }) => {
  let query = await partiesRef.where(`members.${userId}`, '>', 0).get()
    .then(function (querySnapshot) {
      querySnapshot.forEach(function (doc) {
        console.log(doc.id, ' => ', doc.data())
      })
    })
    .catch(function (error) {
      console.log('Error getting documents: ', error)
    })
}

画像のとおり、firestore上のmember.uri_mに正しく数字が登録されており、where区は正しく働く。

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10