On Thu, 19 Sep 2013 21:07:37 GMT, Craig Dillabaugh wrote:

Hello,

I have a JSON document read in from MongoDB and want to access some field that contains another Json object (as a child) and an array of Json objects as another child. The key for the field is called 'gtlayer' in my particular document. I can access this object in the Mongo client using the following:

db.projects.find( { }, { gtlayer: 1 } )

Inside my gtlayer json object there is an object called shape the value of which is an array describing various shapes. My ultimate goal is to read all the shape objects into an array of D classes representing the various shapes. Anyway I am stumped on how to properly get at this data. I currently do the following:

auto cur_proj = projects.find( Bson.EmptyObject, ["gtlayer": 1] ); \\Get a cursor to the database.
   
if( cur_proj.empty() ) {
    //write some error message.
} else {
    Json gtlayer = Json.EmptyObject;

    foreach( Bson bs; cur_proj ) {
        Json doc = bs.toJson();
	/* How do I check if current doc is "_id" or "gtlayer" ???
         * Alternately can I find the correct object/document without using the
         * foreach loop at all, as that would seem preferable. 
         */
         if( / *found it */ ) {
            gtlayer = doc;
            break;
          }
      }

      //Skips some sanity checks.
      auto shapes = gtlayer["shapes"].get!Json; //Is this how I get the 'Shapes' object?

Thanks for any help.

Craig

Okay, so cur_proj will iterate over all documents in the "projects" collection and each returned Bson document will have the form {"_id": ObjectID(...), "gtlayer": ...}. So to get the gtlayer.shapes field, you could just do the following:

auto cur_proj = projects.find( Bson.EmptyObject, ["gtlayer": 1] ); \\Get a cursor to the database.
foreach (bs; cur_proj) {
    assert(!bs.gtlayer.isNull());
    auto shapes = bs.gtlayer.shapes.get!(Bson[]);
    Shape[] ret = shapes.map!(deserializeBson!Shape).array;
    // ...
}

If you only ever have a single document in the collection, or intend to find just a single one, findOne would be the right approach:

auto bs = projects.findOne(Bson.EmptyObject, ["gtlayer": 1]);
enforce(!bs.isNull(), "Couldn't find project");
assert(!bs.gtlayer.isNull());
auto shapes = bs.gtlayer.shapes.get!(Bson[]);
Shape[] ret = shapes.map!(deserializeBson!Shape).array;
// ...

That is assuming that Shape can be Bson (de)serialized properly (i.e. it either has all fields publicly accessible or has read/write properties for each of them or has fromBson/toBson methods).

...it's very possible that I got something totally wrong about the problem, though. I'll try again if this doesn't make sense ;)