I have set up a mongo cluster as follows:

  1. 3 shards, one per global region APAC/EMEA/AMER (in different data centres)
  3. The "writing" clients for the cluster [typically] connect to the mongos in their region, and will be writing documents with their region's region.
  4. The "reading" clients for the cluster [typically] connect to the mongos in their region, and will be reading documents from across multiple regions (broadcast query).

The system is highly write intensive, with very few reads. Thus, overall I believe the above setup is optimal, since writers get fast "local" writes, while readers get convenience of single query to read across the shard, albeit slightly slow [and just to underline, for reading, I value convenience over speed].

OK so that's the background. But then suddenly I realized: I'm also using GridFS to store files, and I want the files to get stored in same way (i.e. write to local region).

Hopefully in the context of the above, my original question makes sense:

How to define shardKey on GridFS collections (fs.files/fs.chunks) to achieve Location/Data Centre affinity?

This is what I've tried:

I've noticed that I can add meta-data in during the upload operation, such that the fs.FILES collection has the region in as an accessible field that could be used as part of the sharding key for fs.files (i.e. sharding key REGION + "FILE_ID").

However, what about fs.chunks? will they follow around their "parent" fs.file record and get routed to the same shard as the "parent" fs.file?

Thanks in advance!

  • note that I'm aware the monotonically increasing primary key creates a hotspot - but that's not the focus of the question.
    – ubienewbie
    Aug 9, 2017 at 6:31

2 Answers 2


However, what about fs.chunks? will they follow around their "parent" fs.file record and get routed to the same shard as the "parent" fs.file?

The answer is no!

You could use files.aliases or files.metadata to store that REGION.

How ever maybe best solution (both chunks and files) is NOT to shard your GridFS. Create three different GridFS databases (APAC/EMEA/AMER) and then use command movePrimary to change "primary shard" to point right shard in your cluster. Then change your application so that it selects GridFS database base on the user's location. This, of course, works with all other collections what are REGION specific.

  • thanks but I can't quite get my head around this: my document sharding setup seems perfect for achieving the desired outcome (fast local writes, unified albeit slow global reads). Is there no way to set up sharding of GridFS files/chunks to achieve same effect? Or do you have to do some kind of workaround like the one you describe?
    – ubienewbie
    Aug 14, 2017 at 10:16
  • When you shard collection, location of the chunk (where documents are) is selected by sharding key what exists in the stored document. Tag aware sharding tags are just list of ranges what describes "to where" those chunk ranges must be located (balanced). Only way to absolutely locate fs.chunks to specific shard is to describe that shard is "primary shard" for THAT database where gridFS is created. Please study more sharding, so you understand "limitations" and how sharding really works.
    – JJussi
    Aug 14, 2017 at 16:38
  • Thanks @JJussi. I feel that I do understand sufficiently how sharding really works, evidenced by the fact that I have (I believe) used sharding very correctly to shard my documents collection to achieve data centre locality. What I do not understand is whether it is possible to apply that exact same technique to fs.chunks. Anyway, I'm getting the feeling that no, it's not possible to shard fs.chunks such that files stay close to their local region just like documents and that yes, you do need to use a workaround. So, i'll look into movePrimary. Cheers!
    – ubienewbie
    Aug 16, 2017 at 9:50

OK I have done some more research into this and this achieves what I want functionally.

  1. The chunks collections can ONLY be sharded on files_id or files_id,n.

  2. So, rather than accepting the default ObjectId() _id given to a file uploaded into fs.files (which is used as the files_id "parent" value in fs.chunks), I have used the MongoGridFSCreateOptions object to set the _id/files_id to a value which is composed of the value I want to shard on plus a GUID. Now I can shard fs.chunks just fine.

            using (var fs = new FileStream(tempZipFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                var createOptions = new MongoDB.Driver.GridFS.MongoGridFSCreateOptions()
                    Id = new BsonString(valueIWantToShardOn + "." + Guid.NewGuid())
                var gridFsInfo = database.GridFS.Upload(fs, Path.GetFileName(tempZipFileName), createOptions);

Not pretty perhaps but gets the job done!

  • Uh oh - got feeling that the above technique only works with older versions of the c# driver. The code from the answer works with version 1.1 of c# driver. I'm now trying to upgrade to version 2.3 and it appears that the ability to set a custom ID for a gridFs file upload is GONE. Currently stuck on what to do about this.
    – ubienewbie
    Sep 21, 2017 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.