MongoDB(Mgo v2)投影返回父结构体。

huangapple go评论85阅读模式
英文:

MongoDB (Mgo v2) Projection returns parent struct

问题

我这里有一个Building对象,里面有一个Floor对象的数组。

在进行投影时,我的目标是根据匹配的元素返回或计算Building对象中Floor对象的数量。代码如下:

对象:

type Floor struct {
    // 二进制JSON标识
    ID bson.ObjectId `bson:"_id,omitempty"`
    // 应用级标识
    FloorUUID string `bson:"f"`
    // 楼层信息
    FloorNumber int `bson:"l"`
    // 单元
    FloorUnits []string `bson:"u"`
    // 统计信息
    Created time.Time `bson:"y"`
}

type Building struct {
    // 二进制JSON标识
    ID bson.ObjectId `bson:"_id,omitempty"`
    // 应用级标识
    BldgUUID string `bson:"b"`
    // 地址信息
    BldgNumber  string `bson:"i"` // 街道号码
    BldgStreet  string `bson:"s"` // 街道
    BldgCity    string `bson:"c"` // 城市
    BldgState   string `bson:"t"` // 州/省
    BldgCountry string `bson:"x"` // 国家
    // 建筑信息
    BldgName      string `bson:"w"`
    BldgOwner     string `bson:"o"`
    BldgMaxTenant int    `bson:"m"`
    BldgNumTenant int    `bson:"n"`
    // 楼层
    BldgFloors []Floor `bson:"p"`
    // 统计信息
    Created time.Time `bson:"z"`
}

代码:

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

    fmt.Println(bldg_uuid)
    fmt.Println(fnum) // 楼层号码

    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")
}

结果发现,无论我如何尝试,查询都返回一个Building对象,而不是一个Floor对象。为了使查询获取和计算楼层而不是建筑物,我需要做出哪些改变?

这样做是为了在插入之前检查Building内是否已经存在一个Floor。如果有更好的方法,我会用更好的方法替换我的方法!

谢谢!

英文:

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!

答案1

得分: 1

您正在查询一个名为Building的文档,所以mongo会返回该文档,即使您尝试使用投影来隐藏其中的一些字段。

我不知道如何在find查询中计算mongo数组中的元素数量,但您可以使用聚合框架,在其中使用$size操作符来实现这一点。因此,您应该向mongo发送以下查询:

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

go中,它看起来像这样:

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)

以上是翻译好的内容,请查看。

英文:

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)

huangapple
  • 本文由 发表于 2015年11月25日 22:41:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/33919366.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定