0

I have here a Building Object where inside sits an Array of Floor Objects.

When Projecting, my goal is to return or count the number of Floor Objects inside a Building Object after matching the elements accordingly. The code is as follows:

Objects:

type Floor struct {
    // Binary JSON Identity
    ID bson.ObjectId `bson:"_id,omitempty"`
    // App-level Identity
    FloorUUID string `bson:"f"`
    // Floor Info
    FloorNumber int `bson:"l"`
    // Units
    FloorUnits []string `bson:"u"`
    // Statistics
    Created time.Time `bson:"y"`
}

type Building struct {
    // Binary JSON Identity
    ID bson.ObjectId `bson:"_id,omitempty"`
    // App-level Identity
    BldgUUID string `bson:"b"`
    // Address Info
    BldgNumber  string `bson:"i"` // Street Number
    BldgStreet  string `bson:"s"` // Street
    BldgCity    string `bson:"c"` // City
    BldgState   string `bson:"t"` // State
    BldgCountry string `bson:"x"` // Country
    // Building Info
    BldgName      string `bson:"w"`
    BldgOwner     string `bson:"o"`
    BldgMaxTenant int    `bson:"m"`
    BldgNumTenant int    `bson:"n"`
    // Floors
    BldgFloors []Floor `bson:"p"`
    // Statistics
    Created time.Time `bson:"z"`
}

Code:

func InsertFloor(database *mgo.Database, bldg_uuid string, fnum int) error {

    fmt.Println(bldg_uuid)
    fmt.Println(fnum) // Floor Number

    var result Floor // result := Floor{}

    database.C("buildings").Find(bson.M{"b": bldg_uuid}).Select(
        bson.M{"p": bson.M{"$elemMatch": bson.M{"l": fnum}}}).One(&result)

    fmt.Printf("AHA %s", result)
    return errors.New("x")
}

It turns out, no matter how I try the query returns a Building Object, not a floor object? What changes do I need to make in order to have the query fetch and count Floors and not Buildings?

This is done so to check if a Floor inside Building already exists before insertion. If there's a better a approach then I'll replace mine with the better!

Thanks!

Community
  • 1
  • 1
William Yang
  • 759
  • 9
  • 30

1 Answers1

1

You are querying for a Building document so mongo returns that to you even though you try to mask some of its fields using projection.

I don't know of a way to count the number of elements in a mongo array in a find query, but you can use the aggregation framework, where you have the $size operator that does exactly this. So you should send a query like this to mongo :

db.buildings.aggregate([
{
    "$match":
    {
        "_id": buildingID,
        "p": {
             "$elemMatch": {"l": fNum}
         }
    }
},
{
    "$project":
    {
        nrOfFloors: {
            "$size": "$p"
        }
    }
}])

Which in go it would look like

result := []bson.M{}
match := bson.M{"$match": bson.M{"b": bldg_uuid, "p": bson.M{"$elemMatch": bson.M{"l": fNum}}}}
count := bson.M{"$project": bson.M{"nrOfFloors": bson.M{"$size": "$p"}}}
operations := []bson.M{match, count}
pipe := sess.DB("mgodb").C("building").Pipe(operations) 
pipe.All(&result)
Pio
  • 4,044
  • 11
  • 46
  • 81
  • But I thought the floor is already inside an array inside Building? Did you read the code?? The unique ID's are there to make things handy. It has nothing to do with mongo's NoSQL philosophy. – William Yang Nov 25 '15 at 18:34