英文:
Golang find a value from a map of nested json data from MongoDB
问题
我正在尝试使用MGO从我的MongoDB接收数据,数据类型为[]map[string]interface{}。
我的JSON数据如下所示:
{
   "_id":"string",
   "brandId":123,
   "category":{
      "television":[
         {
            "cat":"T1",
            "subCategory":[
               {
                  "subCat":"T1A TV",
                  "warrantyPeriod":6
               }
            ],
            "warrantyPeriod":12
         },
         {
            "cat":"T2",
            "subCategory":[
               {
                  "subCat":"T2A",
                  "warrantyPeriod":18
               },
               {
                  "subCat":"T2B",
                  "warrantyPeriod":9
               }
            ],
            "warrantyPeriod":15
         },
         {
            "cat":"T3",
            "subCategory":[
               {
                  "subCat":"T3A",
                  "warrantyPeriod":3
               },
               {
                  "subCat":"T3B",
                  "warrantyPeriod":5
               },
               {
                  "subCat":"T3C",
                  "warrantyPeriod":7
               },
               {
                  "subCat":"T3D",
                  "warrantyPeriod":11
               }
            ],
            "warrantyPeriod":4
         }
      ],
      "television_warrantyPeriod":24
   },
   "title":"BrandName"
}
我希望传入类别名称,例如'television',以及可选的cat和subCat值。
例如:
{
"categorySlug": "television",
"brandId": "123",
"model": "T2"
}
在这种情况下,如果没有指定T2A或T2B,我希望找到'15',即T2的warrantyPeriod值。
我的查询函数如下所示:
var data map[string]string
err := json.NewDecoder(r.Body).Decode(&data)
log.Println(err)
var buffer bytes.Buffer
buffer.WriteString("category.")
buffer.WriteString(data["categorySlug"])
brandId, _ := strconv.Atoi(data["brandId"])
concernedbrandandcategory := database.GetMappedFields("Brands", bson.M{"brandId": brandId, buffer.String(): bson.M{"$exists": true}}, bson.M{buffer.String(): 1})
categorymap := concernedbrandandcategory[0]
log.Println(categorymap["category"]["television"], reflect.TypeOf(categorymap))
我的GetMappedFields函数如下所示:
func GetMappedFields(collectionName string, query interface{}, selector interface{}) (result []map[string]interface{}) {
    MgoSession.DB(Dbname).C(collectionName).Find(query).Select(selector).All(&result)
    return
}
我无法理解这个嵌套结构,有时返回一个map,有时返回一个interface!任何帮助将不胜感激!
英文:
I am trying to receive data from my MongoDB using MGO in a map of type []map[string]interface{}
My JSON looks like this -
{
   "_id":"string",
   "brandId":123,
   "category":{
      "television":[
         {
            "cat":"T1",
            "subCategory":[
               {
                  "subCat":"T1A TV",
                  "warrantyPeriod":6
               }
            ],
            "warrantyPeriod":12
         },
         {
            "cat":"T2",
            "subCategory":[
               {
                  "subCat":"T2A",
                  "warrantyPeriod":18
               },
               {
                  "subCat":"T2B",
                  "warrantyPeriod":9
               }
            ],
            "warrantyPeriod":15
         },
         {
            "cat":"T3",
            "subCategory":[
               {
                  "subCat":"T3A",
                  "warrantyPeriod":3
               },
               {
                  "subCat":"T3B",
                  "warrantyPeriod":5
               },
               {
                  "subCat":"T3C",
                  "warrantyPeriod":7
               },
               {
                  "subCat":"T3D",
                  "warrantyPeriod":11
               }
            ],
            "warrantyPeriod":4
         }
      ],
      "television_warrantyPeriod":24
   },
   "title":"BrandName"
}
I would ideally pass in the category name i.e. 'television' and cat and subCat values which could be optional.
For e.g. something like this -
{
"categorySlug": "television",
"brandId": "123",
"model": "T2"
}
In which case I would expect to find '15' which is the warrantyPeriod value for T2 if there are no T2A or T2B specified.
My query functions look like this -
var data map[string]string
err := json.NewDecoder(r.Body).Decode(&data)
log.Println(err)
var buffer bytes.Buffer
buffer.WriteString("category.")
buffer.WriteString(data["categorySlug"])
brandId, _ := strconv.Atoi(data["brandId"])
concernedbrandandcategory := database.GetMappedFields("Brands", bson.M{"brandId": brandId, buffer.String(): bson.M{"$exists": true}}, bson.M{buffer.String(): 1})
categorymap := concernedbrandandcategory[0]
log.Println(categorymap["category"]["television"], reflect.TypeOf(categorymap))
My GetMappedFields function looks like this -
func GetMappedFields(collectionName string, query interface{}, selector interface{}) (result []map[string]interface{}) {
	MgoSession.DB(Dbname).C(collectionName).Find(query).Select(selector).All(&result)
	return
}
I'm just not able to wrap my head around this nested structure which sometimes returns a map and sometimes an interface!
Any help would be highly appreciated!
答案1
得分: 1
你可以这样做:
majorCat := body["categorySlug"]
category := body["category"]
subCategory := body["subCategory"]
brandId, err := strconv.Atoi(body["brandId"])
if err != nil {
    log.Println(err)
}
result := database.GetMappedFields("Brands", bson.M{"brandId": brandId}, bson.M{"category": 1, "_id": 0})
internalObj := result[0]["category"].(map[string]interface{})
finalValue := internalObj["television_warrantyPeriod"]
if category != "" {
    for _, v := range internalObj[majorCat].([]interface{}) {
        subObj := v.(map[string]interface{})
        if subObj["cat"] == category {
            finalValue = subObj["warrantyPeriod"]
            if subCategory != "" {
                minorObj := subObj["subCategory"].([]interface{})
                for _, iter := range minorObj {
                    kevVal := iter.(map[string]interface{})
                    if kevVal["subCat"] == subCategory {
                        finalValue = kevVal["warrantyPeriod"]
                    }
                }
            }
        }
    }
}
希望这样可以动态地实现,或者你可以创建一个结构体,以便可以直接解码成该结构体。祝好!
英文:
you can do something like this
    majorCat := body["categorySlug"]
	category := body["category"]
	subCategory := body["subCategory"]
	brandId, err := strconv.Atoi(body["brandId"])
	if err != nil {
		log.Println(err)
	}
	result := database.GetMappedFields("Brands", bson.M{"brandId": brandId}, bson.M{"category": 1, "_id": 0})
	internalObj := result[0]["category"].(map[string]interface{})
	finalValue := internalObj["television_warrantyPeriod"]
	if category != "" {
		for _, v := range internalObj[majorCat].([]interface{}) {
			subObj := v.(map[string]interface{})
			if subObj["cat"] == category {
				finalValue = subObj["warrantyPeriod"]
				if subCategory != "" {
					minorObj := subObj["subCategory"].([]interface{})
					for _, iter := range minorObj {
						kevVal := iter.(map[string]interface{})
						if kevVal["subCat"] == subCategory {
							finalValue = kevVal["warrantyPeriod"]
						}
					}
				}
			}
		}
	}
Hopefully this will do dynamically or you can create a struct so that it can directly be decoded into that cheers
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论