2

我使用 Flamelink 作为与 Firebase 集成的无头 CMS。我所有的字符串字段都工作得很好;我只是在获取上传到 Firebase 存储的媒体的 URL 时遇到了一些麻烦。

我从中获取字符串字段的集合是fl_content 这些字段是:

string1
string2
imageUpload

在 Firebase 中,我可以看到从 Flamelink 保存的数据:

string1: "Titanium Tee"
string2: "Lower your handicap by 50 with premium Titanium golf tees!"

imageUpload 返回一个引用fl_files(Firebase 中的不同集合)的数组

imageUpload:
    0 fl_files/ZqVeXI3vX0rFDuJVDzuR

在 fl_files > ZqVeXI3vX0rFDuJVDzuR 下,我可以看到我上传的图片的完整文件名;中的文档fl_files有一个file字段。我需要将此文件名发送到我的对象,以便能够在我的 UI 中使用图像。

这是我的进展:

任务:

struct Task{
    var string1:String
    var string2:String
    //var imageUpload:String
    var counter:Int
    var id: String

    var dictionary: [String: Any] {
        return [
            "string1": string1,
            "string2": string2,
            //"imageUpload": imageUpload,
            "counter": counter
        ]
    }
}

extension Task{
    init?(dictionary: [String : Any], id: String) {
        guard   let string1 = dictionary["string1"] as? String,
            let string2 = dictionary["string2"] as? String,
            //let imageUpload = dictionary["imageUpload"] as? String,
            let counter = dictionary["counter"] as? Int
            else { return nil }

        self.init(string1:string1, string2: string2, /*imageUpload: imageUpload,*/ counter: counter, id: id)
    }
}

风险投资:

private var documents: [DocumentSnapshot] = []
public var tasks: [Task] = []
private var listener : ListenerRegistration!

fileprivate func baseQuery() -> Query {
    return Firestore.firestore().collection("fl_content").limit(to: 50)
}

fileprivate var query: Query? {
    didSet {
        if let listener = listener {
            listener.remove()
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.query = baseQuery()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.listener.remove()
}


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    listenerStuff()
}

func listenerStuff(){
    self.listener =  query?.addSnapshotListener { (documents, error) in
        guard let snapshot = documents else {
            print("Error fetching documents results: \(error!)")
            return
        }

        let results = snapshot.documents.map { (document) -> Task in
            if let task = Task(dictionary: document.data(), id: document.documentID) {
                return task
            }
            else {
                fatalError("Unable to initialize type \(Task.self) with dictionary \(document.data())")
            }
        }

        self.tasks = results
        self.documents = snapshot.documents

        self.databaseTableView.reloadData()

    }
}

如何查询 fl_files 以便可以使用上传图像的 URL 填充 Task 的 imageUpload 属性?我做另一个单独的查询吗?或者我可以从 baseQuery() 访问 fl_files 吗?

编辑

这是我从 fl_content 获取 fl_files 的尝试。试图从 Firebase 中简单地填充 2 个文本字段和一个图像字段(在 UITableViewCell 中)。我property在getdocument中需要什么?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "databaseCellID", for: indexPath) as! DatabaseTableViewCell
    let item = tasks[indexPath.row]

    cell.label1.text = item.string1
    cell.label2.text = item.string2
    let docRef = Firestore.firestore().collection("fl_content").document(item.id)
    print("PARENT \(docRef.parent)")
    docRef.getDocument { (document, error) in
        if let document = document, document.exists {
            let property = document.get("imageUpload")
            // TODO - use this property to get to fl_files?
            print("Document data: \(property!)")
        }
    }
}
4

2 回答 2

3

您将需要执行单独的查询。Firestore 中没有类似 SQL 的连接操作,并且不会自动遵循引用。

于 2019-08-19T16:04:06.017 回答
2

最简单的方法可能是编写一个小的云函数,它将响应上传的文件并将图像 URL 自动放置在您想要的集合中,从而更容易查询。

我们将一个onCreate监听器附加到集合中,然后当我们看到创建了一个新文件时fl_files,将下载 URL 写入相应的文档。fl_content请注意,您的实际内容字段可能与我在这里使用的示例不同(我个人对 Flamelink 并不熟悉)。

/**
 * Firebase Cloud Function deployed to your same project.
 */

const functions = require('firebase-functions');
import { firestore } from 'firebase-admin';

exports.newFileUploaded = functions.firestore
  .document('fl_files/{newFileID}')
  .onCreate((snap, context) => { 

    const fileID = context.params.newFileID;
    const fileData = snap.data();

    // get whatever data you want out of fileData..
    // (let's assume there is a downloadURL property with the URL of the image)
    const downloadURL = fileData.downloadURL;

    // write that download URL to the corresponding fl_content document
    // (assuming the file ID is the same as the content ID)
    const contentRef = firestore().collection('fl_content').doc(fileID);

    // update the imageURL property, returning the Promise, so the function
    // does not terminate too early
    const updateData = { imageUpload: downloadURL };
    return contentRef.update(updateData);

});

现在,您只需执行 1 次查询,fl_content新文件的图像 URL 将包含在请求中。我们做出的权衡是我们必须执行 1 次额外的 Firestore 写入,以节省 50% 的所有未来读取请求。

或者,如果没有云函数,我们将不得不执行 2 个单独的查询来从fl_content和获取内容fl_filesJOIN正如 Doug 所提到的,由于 Firestore 的设计方式具有可扩展性,因此不可能使用类似的查询。

于 2020-02-06T09:57:24.557 回答