从 id 数组中获取 firestore 文档列表

Posted

技术标签:

【中文标题】从 id 数组中获取 firestore 文档列表【英文标题】:Get a list of firestore documents from array of id's 【发布时间】:2020-09-07 19:17:40 【问题描述】:

我有一个 firestore 集合,他的值之一是文档 ID 数组。 我需要检索所有集合项目以及存储在数组 id 中的所有文档。 这是我收藏的结构

我的代码:

export const getFeaturedMixes = functions.https.onRequest((request, response) => 
    let result:any[] = []
    featuredMixes.get().then(mixesSnap => 

        mixesSnap.forEach(doc => 
            let docId = doc.id
            let ids = doc.data().tracks

            let resultTracks:any[] = []
            ids.forEach(id => 
                let t = tracksCollection.doc(id.track_id).get()
                resultTracks.push('id' : id.track_id, 'data': t)
            )
            result.push('id':docId, 'tracks': resultTracks)
        )
        return result
    )
    .then(results => 
        response.status(200).send(results)
    ).catch(function(error) 
        response.status(400).send(error)
    )
);

我收到了这样的回复:


        "id": "Xm4TJAnKcXJAuaZr",
        "tracks": [
            
                "id": "FG3xXfldeJBbl8PY6",
                "data": 
                    "domain": 
                        "domain": null,
                        "_events": ,
                        "_eventsCount": 1,
                        "members": []
                    
                
            ,
            
                "id": "ONRfLIh89amSdcLt",
                "data": 
                    "domain": 
                        "domain": null,
                        "_events": ,
                        "_eventsCount": 1,
                        "members": []
                    
                
            
    ]

响应不包含文档数据

【问题讨论】:

【参考方案1】:

get() 方法是异步的,并返回一个 Promise。因此,您不能执行以下操作:

 ids.forEach(id => 
      let t = tracksCollection.doc(id.track_id).get()
      resultTracks.push('id' : id.track_id, 'data': t)
 )

您需要等待get() 方法返回的Promise 解析,才能使用t(即DocumentSnapshot)。

为此,由于您要并行获取多个文档,因此需要使用Promise.all()

以下应该可以解决问题。请注意,它没有经过测试,并且您仍然可以完成代码的简单部分,请参阅最后的 cmets。如果您在完成时遇到问题,请将您的新代码添加到您的问题中。

export const getFeaturedMixes = functions.https.onRequest((request, response) => 
    let result: any[] = []

    const docIds = [];

    featuredMixes.get()
        .then(mixesSnap => 


            mixesSnap.forEach(doc => 
                let docId = doc.id
                let ids = doc.data().tracks

                const promises = []

                ids.forEach(id => 
                    docIds.push(docId);
                    promises.push(tracksCollection.doc(id.track_id).get())
                )

            )

            return Promise.all(promises)
        )
        .then(documentSnapshotArray => 

            // Here documentSnapshotArray is an array of DocumentSnapshot corresponding to
            // the data of all the documents with track_ids

            // In addition, docIds is an array of all the ids of the FeaturedMixes document

            // IMPORTANT: These two arrays have the same length and are ordered the same way

            //I let you write the code to generate the object you want to send back to the client: loop over those two arrays in parallel and build your object


            let resultTracks: any[] = []

            documentSnapshotArray.forEach((doc, idx) => 
                // .....
                // Use the idx index to read the two Arrays in parallel

            )

            response.status(200).send(results)

        )
        .catch(function (error) 
            response.status(400).send(error)
        )
);

【讨论】:

【参考方案2】:

谢谢雷诺塔内克!!你的回答真的很有希望,功能已经在工作,但是我想返回 Promise.all(primises) 一些对象,其中包含 mix 和他的曲目,因为现在很难构建then 函数中的新对象, 这是我的最终功能

    const mixIDs: any[] = [];
    const mixes:any[] =[]

    featuredMixes.get()
        .then(mixesSnap => 
            const promises:any[] = []

            mixesSnap.forEach(doc => 
                let mixId = doc.id
                let mix = createMix(doc)
                mixes.push(mix)

                doc.data().tracks.forEach(track => 
                    let promise = tracksCollection.doc(track.track_id).get()
                    promises.push(promise)
                    mixIDs.push(mixId)
                )
            )
            return Promise.all(promises)
        )
        .then(tracksSnapshot => 

            let buildedTracks = tracksSnapshot.map((doc, idx) => 
                let mId = mixIDs[idx]
                return createTrack(doc, mId)
            )

            let result = mixes.map(mix => 
                let filterTracks = buildedTracks.filter(x => x.mix_id === mix.doc_id)
                return Object.assign(mix, 'tracks': filterTracks)
            )
            response.status(200).send(result)
        )
        .catch(function (error) 
            response.status(400).send(error)
        )
)

【讨论】:

嗨@vila.puigvila,如果您认为我的回答有帮助,请点赞,见***.com/help/someone-answers

以上是关于从 id 数组中获取 firestore 文档列表的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Firestore 集合中获取所有文档并将它们返回到数组列表中? [复制]

如何在firestore中获取文档,其文档ID存储在列表中?,即只带那些文档....?

如何在 swift iOS Firestore 中获取单元格文档 ID?

如何从对象中获取 FireStore 文档 ID?

在 Swift 中从 Firestore 中获取文档列表

Firestore 从集合中获取文档 ID