【问题标题】:Querying MongoDB GridFS?查询 MongoDB GridFS?
【发布时间】:2012-01-20 22:33:33
【问题描述】:

我有一个博客系统,可以将上传的文件存储到 GridFS 系统中。问题是,我不明白怎么查询!

我将 Mongoose 与尚不支持 GridFS 的 NodeJS 一起使用,因此我将实际的 mongodb 模块用于 GridFS 操作。似乎没有一种方法可以像查询常规集合中的文档那样查询文件元数据。

将元数据存储在指向 GridFS objectId 的文档中是否明智?方便查询?

任何帮助将不胜感激,我有点卡住了:/

【问题讨论】:

    标签: mongodb node.js mongoose gridfs


    【解决方案1】:

    我知道这个问题并没有询问 Java 查询元数据的方式,但在这里,假设您将 gender 添加为元数据字段:

    // Get your database's GridFS
    GridFS gfs = new GridFS("myDatabase);
    
    // Write out your JSON query within JSON.parse() and cast it as a DBObject
    DBObject dbObject = (DBObject) JSON.parse("{metadata: {gender: 'Male'}}");
    
    // Querying action (find)
    List<GridFSDBFile> gridFSDBFiles = gfs.find(dbObject);
    
    // Loop through the results
    for (GridFSDBFile gridFSDBFile : gridFSDBFiles) {
        System.out.println(gridFSDBFile.getFilename());
    }
    

    【讨论】:

    • 为什么不赞成?
    【解决方案2】:

    正如specification 所说,您可以在元数据字段中存储您想要的任何内容。

    文件集合中的文档如下所示:

    必填字段

    {
      "_id" : <unspecified>,                  // unique ID for this file
      "length" : data_number,                 // size of the file in bytes
      "chunkSize" : data_number,              // size of each of the chunks.  Default is 256k
      "uploadDate" : data_date,               // date when object first stored
      "md5" : data_string                     // result of running the "filemd5" command on this file's chunks
    }
    

    可选字段

    {    
      "filename" : data_string,               // human name for the file
      "contentType" : data_string,            // valid mime type for the object
      "aliases" : data_array of data_string,  // optional array of alias strings
      "metadata" : data_object,               // anything the user wants to store
    }
    

    所以在元数据中存储你想要的任何东西,然后像在 MongoDB 中一样正常查询它:

    db.fs.files.find({"metadata.some_info" : "sample"});
    

    【讨论】:

      【解决方案3】:

      GridFS 通过为每个文件存储多个块来工作。这样,您可以交付和存储非常大的文件,而无需将整个文件存储在 RAM 中。此外,这使您能够存储大于最大文档大小的文件。建议的块大小为 256kb。

      文件元数据字段可用于存储其他特定于文件的元数据,这比将元数据存储在单独的文档中更有效。这在很大程度上取决于您的确切要求,但元数据字段通常提供了很大的灵活性。请记住,默认情况下,一些更明显的元数据已经是 fs.files 文档的一部分:

      > db.fs.files.findOne();
      {
          "_id" : ObjectId("4f9d4172b2ceac15506445e1"),
          "filename" : "2e117dc7f5ba434c90be29c767426c29",
          "length" : 486912,
          "chunkSize" : 262144,
          "uploadDate" : ISODate("2011-10-18T09:05:54.851Z"),
          "md5" : "4f31970165766913fdece5417f7fa4a8",
          "contentType" : "application/pdf"
      }
      

      要真正从 GridFS 读取文件,您必须从 fs.files 获取文件文档并从 fs.chunks 获取块。最有效的方法是逐块将其流式传输到客户端,因此您不必将整个文件加载到 RAM 中。 chunks 集合具有以下结构:

      > db.fs.chunks.findOne({}, {"data" :0});
      {
          "_id" : ObjectId("4e9d4172b2ceac15506445e1"),
          "files_id" : ObjectId("4f9d4172b2ceac15506445e1"),
          "n" : 0, // this is the 0th chunk of the file
          "data" : /* loads of data */
      }
      

      如果您想使用fs.filesmetadata 字段进行查询,请确保您了解dot notation,例如

      > db.fs.files.find({"metadata.OwnerId": new ObjectId("..."), 
                          "metadata.ImageWidth" : 280});
      

      还要确保您的查询可以使用使用explain() 的索引。

      【讨论】:

      • 如何在元数据字段上创建可用索引?
      • 您可以简单地创建一个像{ fs.files.metadata.my_field : 1} 这样的索引,没有架构可以大大简化一些事情
      【解决方案4】:

      元数据存储在元数据字段中。你可以像这样查询它

      db.fs.files.find({metadata: {content_type: 'text/html'}}) 
      

      【讨论】:

      • 这可能不是 OP 所期望的。该语法将查找子文档的 exact 匹配项,即您的查询将 not 匹配 "metadata" : { "content_type" : "text/html", "foo" : "bar" }。此外,该示例可能会造成混淆,因为 content_typefs.files 结构的一部分,但在那里有不同的名称。
      猜你喜欢
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 2015-03-04
      相关资源
      最近更新 更多