假设我有一系列评论。每个评论对象都有一个“doc ref”给发布的用户。我需要一个返回注释列表的查询,包括每个用户引用的值,所以我的查询返回一个很好的格式化的Json注释对象。
答案 0 :(得分:10)
此处提出了类似的问题What is firestore Reference data type good for?,根据这个回答https://stackoverflow.com/a/46570119/473453,我认为不可能按照您的要求做任何事情。
您必须自己加载每个引用,例如
const comments = []
firebase.firestore().collection('/comments').get().then(snapshot => {
snapshot.docs.forEach(doc => {
const comment = doc.data()
comment.userRef.get().then(snap => {
comment.user = snap.data()
comments.push(comment)
})
})
})
对于许多评论,这将增加很多开销。也许你可以在服务器端编写一个为你们所有人工作的CloudFunction,并返回一个格式化的JSON。
看起来他们可能会在未来继续支持这项工作:https://stackoverflow.com/a/46614683/473453
答案 1 :(得分:3)
我建议你在每条评论中复制用户数据。在注释文档中创建一个名为user
的对象的字段,并提供显示注释所需的最少信息量。因此,您的comment
doc可能看起来像......
{
id: 'CEXwQAHpk61vC0ulSdZy',
text: 'This is a comment',
user: {
id: 'd5O4jTsLZHXmD1VJXwoE,
name: 'Charlie Martin',
avatar: 'https://...'
}
}
现在,您拥有显示评论所需的一切。如果有人点击评论的作者,您可以获取该ID并使用它来加载评论员的完整个人资料。
数据复制在关系数据库中不受欢迎,因为它们是为使用外键处理这些场景而构建的。
然而,在像firestore这样的NoSQL数据库中,实际上鼓励数据重复来简化查询并减少通过网络发送的数据量。
如果您为每条评论加载了完整的user
文档,则可能会加载有关用户的更多信息,而不是显示评论所需的信息。
答案 2 :(得分:1)
这也惹恼了我。我做了一个实用程序助手,它可以自动填充第一级。
助手
import { get, set } from 'lodash'
const getReference = async documentReference => {
const res = await documentReference.get()
const data = res.data()
if (data && documentReference.id) {
data.uid = documentReference.id
}
return data
}
const hydrate = async (document, paths = []) => Promise.all(
paths.map(async path => {
const documentReference = get(document, path)
if (!documentReference || !documentReference.path) {
return console.warn(
`Error hydrating documentReference for path "${path}": Not found or invalid reference`
)
}
const result = await getReference(documentReference)
set(document, path, result)
})
)
}
export { hydrate }
用法示例:
getUser = async uid => {
return this.db
.collection('users')
.doc(uid)
.get()
.then(async documentSnapshot => {
const data = documentSnapshot.data()
await hydrate(data, ['company', 'someOtherNestedRef-2', 'someOtherNestedRef-1'])
return data
})
}
限制:此示例不适用于深层嵌套引用
答案 3 :(得分:1)
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("Stock").whereEqualTo("user", userName).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isComplete()) {
Log.d(TAG, "onComplete stock : "+ task.getResult().getDocuments().toString());
List<DocumentSnapshot> list = task.getResult().getDocuments();
if (list != null && list.size()>0) {
for (DocumentSnapshot doc: list) {
StockData stockData = new StockData();
stockData.setCatergory(doc.get("catergory").toString());
stockData.setDate(doc.get("date").toString());
stockData.setUser(doc.getString("date_time"));
stockData.setUser(doc.getString("user"));
stockData.setSale_price(doc.getDouble("sale_price"));
}
}
}
}
});
答案 4 :(得分:0)
我为此创建了一个解决方案,至少对我有用!
想象一下,您有2个集合:用户和朋友,而用户有一个文档:User1和朋友也有一个文档:Friend1。
因此,User1的参考字段为以下文本:Friends / Friend1。
U可以获取所有用户,并且您可以为每个用户建立一个这样的地图:
[
{
"User1":"Friend1"
}
{
"Another User":"Another Friend"
}
]
答案 5 :(得分:0)
添加到ChrisRich response。如果所需字段是引用数组,则可以使用以下代码:
import { get, set } from 'lodash'
const getReference = async documentReference => {
const res = await documentReference.get()
const data = res.data()
if (data && documentReference.id) {
data.uid = documentReference.id
}
return data
}
export default async (document, paths = []) => Promise.all(
paths.map(async path => {
const documentField = get(document, path)
if (documentField.constructor.name === 'Array') {
for (let i = 0; i < documentField.length; i++) {
const documentReference = documentField[i];
if (!documentReference || !documentReference.path) {
return console.warn(
`Error hydrating documentReference for path "${path}": Not found or invalid reference`
)
}
const result = await getReference(documentReference)
documentField[i] = result;
}
}
else {
const documentReference = documentField;
if (!documentReference || !documentReference.path) {
return console.warn(
`Error hydrating documentReference for path "${path}": Not found or invalid reference`
)
}
const result = await getReference(documentReference)
set(document, path, result)
}
})
)