Firebase&Firestoreで、名前にドットや空白など記号を含むフィールドに対してクエリ実行する方法を紹介します。
(2020.1.16現在)ドキュメントに書かれている方法ではなぜか正しく動作しません。
前置き(うまくいかない例)
Firestoreではフィールド名にドットや空白など記号を含めて保存することができます。
let db = firebase.firestore();
const testdata = db.collection("data").doc("test");
const doc = {normal:true, map:{}};
doc['dot.test'] = true;
doc.map['normal'] = true;
doc.map['space test'] = true;
doc.map['123456'] = true;
db.collection("data").doc("test").set(doc);
保存されたデータ↓
これらのフィールドをwhere条件にしてクエリを実行します。
通常のフィールド名(アルファベット&数字&アンスコのみ、かつ数字開始ではない)の場合、フィールド名をそのまま文字列で指定すればOKです。
let query = db.collection('data').where('normal', '==', true);
let querySnapshot = await query.get();
querySnapshot.forEach(function(dataRef){
console.log(dataRef.id, dataRef.data());
});
入れ子の場合はドット区切りで指定
query = db.collection('data').where('map.normal', '==', true);
ここからが本題。
ドットや空白などが含まれるフィールドをそのまま検索してみます。
query = db.collection('data').where('dot.test', '==', true);
query = db.collection('data').where('map.dot.test', '==', true);
これだと結果が返ってきません(空白を含むフィールドも同様)。
ドキュメントを見ると下記の様に書かれています。
Constraints on field paths
- Must separate field names with a single period (.)
- Must enclose each field name in backticks unless the field name meets the following requirements:
- The field name contains only the characters a-z, A-Z, 0-9, and underscore (_)
- The field name does not start with 0-9
言われるがままバッククォートで囲んでみます。
query = db.collection('data').where('`dot.test`', '==', true);
しかしこれでも結果は返ってきません。
正しい方法
どうもドキュメントが間違っていて正しくはfirebase.firestore.FieldPathを使用する必要がある様です。
query.where(new firebase.firestore.FieldPath("dot.test"), "==", true)
入れ子やmapの場合
query.where(new firebase.firestore.FieldPath("map", "dot.test"), "==", true)
参考:
firebase - Firestore Query Properties with special characters - Stack Overflow
これで結果が返ってきました🎉
ちなみに「どんなときにフィールド名に記号とか保存するんだよw」と思われる方もいるかもしれませんので使用例をリンクしておきます^^
https://blog.knightso.co.jp/entry/2020/01/16/042702