mongodb GridFS 大结构文件系统

GridFS是一种在MongoDB中存储大二进制文件的机制。使用GridFS存文件有如下几个原因:

1、利用Grid可以简化需求。要是已经用了MongoDB,GridFS就可以不需要使用独立文件存储架构。
2、GridFS会直接利用业已建立的复制或分片机制,所以对于文件存储来说故障恢复和扩展都很容易。
3、GridFS可以避免用于存储用户上传内容的文件系统出现的某些问题。例如,
GridFS在同一个目录下放置大量的文件是没有任何问题的。
4、GridFS不产生磁盘碎片,因为MongoDB分配数据文件空间时以2GB为一块。

使用场景:

1) 有大量的上传图片(用户上传或者系统本身的文件发布等)
2) 文件的量级处于飞速增长,有可能打到单机操作系统自己的文件系统的查询性能瓶颈,甚至超过单机硬盘的扩容范围.
3) 文件的备份(不适用gridfs这种三方也可以做,但是不尽方便),文件系统访问的故障转移和修复..
4) 文件的索引,存储除文件本身以外还需要关联更多的元数据信息(比如,不仅仅存储文件,还要保存一些文件的发布式作者/发布时间/文件tag属性等等自定义信息)并且需要索引的。
5) 基于4),对文件的分类模糊,如果采用操作系统的文件系统,文件夹分类关系混乱或者无法分类时
6) 当前系统是基于web的,对图片的访问根据url了规则路由的..(如搭配nginx用,让nginx直接读取gridfs的文件)
7) 文件尺寸较小,而且众多,且文件有可能被迁移/删除等
8)用于存储和恢复那些超过16M(BSON文件限制)的文件

接口代码如下:
mongoc_gridfs_t提供的是MongoDB 的gridfs 文件系统的接口。地理信息文件系统包含gridfs_filesgridfs_file_lists以及相关的api。
mongoc_gridfs_t 是非线程安全的。释放mongoc_gridfs_t之前需要先释放mongoc_gridfs_file_tmongoc_gridfs_file_list_t

示例代码如下

#include <mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main (int argc, char *argv[])
{
   mongoc_gridfs_t *gridfs;
   mongoc_gridfs_file_t *file;
   mongoc_gridfs_file_list_t *list;
   mongoc_gridfs_file_opt_t opt = { 0 };
   mongoc_client_t *client;
   mongoc_stream_t *stream;
   bson_t query;
   bson_t child;
   bson_error_t error;
   ssize_t r;
   char buf[4096];
   mongoc_iovec_t iov;
   const char * filename;
   const char * command;
   if (argc < 2) {
      fprintf(stderr, "usage - %s command ...\n", argv[0]);
      return 1;
   }
   mongoc_init();
   iov.iov_base = (void *)buf;
   iov.iov_len = sizeof buf;
   /* connect to localhost client */
   client = mongoc_client_new ("mongodb://127.0.0.1:27017");//创建连接
   assert(client);//检查创建连接结果
   /* grab a gridfs handle in test prefixed by fs */
   gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
   assert(gridfs);
   command = argv[1];
   filename = argv[2];
   if (strcmp(command, "read") == 0) {//读取指定文档
      if (argc != 3) {
         fprintf(stderr, "usage - %s read filename\n", argv[0]);
         return 1;
      }
      file = mongoc_gridfs_find_one_by_filename(gridfs, filename, &error);
      assert(file);
      stream = mongoc_stream_gridfs_new (file);
      assert(stream);
      for (;;) {
         r = mongoc_stream_readv (stream, &iov, 1, -1, 0);
         assert (r >= 0);
         if (r == 0) {
            break;
         }
         if (fwrite (iov.iov_base, 1, r, stdout) != r) {
            MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
            exit (1);
         }
      }
      mongoc_stream_destroy (stream);
      mongoc_gridfs_file_destroy (file);
   } else if (strcmp(command, "list") == 0) {//列举所有文档
      bson_init (&query);
      bson_append_document_begin (&query, "$orderby", -1, &child);
      bson_append_int32 (&child, "filename", -1, 1);
      bson_append_document_end (&query, &child);
      bson_append_document_begin (&query, "$query", -1, &child);
      bson_append_document_end (&query, &child);
      list = mongoc_gridfs_find (gridfs, &query);
      bson_destroy (&query);
      while ((file = mongoc_gridfs_file_list_next (list))) {
         const char * name = mongoc_gridfs_file_get_filename(file);
         printf("%s\n", name ? name : "?");
         mongoc_gridfs_file_destroy (file);
      }
      mongoc_gridfs_file_list_destroy (list);
   } else if (strcmp(command, "write") == 0) {//写文档
      if (argc != 4) {
         fprintf(stderr, "usage - %s write filename input_file\n", argv[0]);
         return 1;
      }
      stream = mongoc_stream_file_new_for_path (argv [3], O_RDONLY, 0);
      assert (stream);
      opt.filename = filename;
      file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
      assert(file);
      mongoc_gridfs_file_save(file);
      mongoc_gridfs_file_destroy(file);
   } else {
      fprintf(stderr, "Unknown command");
      return 1;
   }
   mongoc_gridfs_destroy (gridfs);
   mongoc_client_destroy (client);
   mongoc_cleanup ();
   return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值