Z
Z
zebox2017-11-08 16:59:35
MongoDB
zebox, 2017-11-08 16:59:35

Editing and deleting nested array elements in MongoDB on Go?

Hello!
People tell me how to implement operations (editing \ deleting) with elements of an array nested in a document?
Document structure:

{
"user_id": 123
"categories": [
      {
      "category_name": "entertainment"
      "tags": [
           	{
            "list_name": "games",
            "discription": "video games tags",
            "list": ["psp","xbox","pc"]
            },
            {
            "list_name": "tvshow",
            "discription": "any tvshow",
            "list": ["got","dexter","arrow"]
            }
          ]
      },
      {
      "category_name": "sports"
      "tags": [
           	{
            "list_name": "summer",
            "discription": "summer sport",
            "list": ["tennis","swimming","jumping"]
            },
            {
            "list_name": "winter",
            "discription": "winter sport",
            "list": ["hockey","biathlon","ski"]
            }
          ]
      }
  ]
}

I figured out adding and checking for uniqueness, but I can’t figure out how to do it with deleting and editing. For example, you need to edit list_name=summer to sum in the sport category, or remove the list_name=tvshow element from the entertainment category .
I'm trying to remove it like this:
colQuerier := bson.M{
"user_id": "123", 
"categories": bson.M{
  "$elemMatch": bson.M{
  		"category_name": "entertainment", 
    "tags": bson.M{
        "$elemMatch": bson.M {"list_name": "tvshow"}
    }
  }
  }
}

change := bson.M{"$pull": bson.M{"categories.$.tags": bson.M{"list_name": "tvshow"}}}
err = c.Update(colQuerier, change)

But the delete doesn't work.
MongoDBv. 3.4
I still can't understand how to implement editing...
Please help me figure it out.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
Z
zebox, 2017-11-10
@zebox

Issue resolved!
Perhaps through a crutch (because it could probably be implemented through $map or $filter), but in the end everything works as it should.

//выбираем документ и устанавливаем на него курсор.
colQuerier := bson.M{"user_id": "123", "categories": bson.M{"$elemMatch": bson.M{"category_name": "entertainment", "tags": bson.M{"$elemMatch": bson.M{"list_name": "tvshow"}}}}} 

//удалаем элемент вложенного массива использя оператор проекции
change := bson.M{"$pull": bson.M{"categories.$.tags": bson.M{"list_name": "tvshow"}}}

err = c.Update(colQuerier, change)

Since. operator "$" can be used only for one array, it is necessary to initially find the index of the main array, and then execute a query with an explicit indication of the index of the element to select the nested document (array).
//создаем пустой интерфейс для получения данных агрегации
var resp interface{}

//Используем механизм агрегации данных с проекцией для получения индекса основного массива
pipe := c.Pipe([]bson.M{{"$match": bson.M{"user_id": user_id}}, {"$project": bson.M{"_id": 0, "matchedIndex": bson.M{"$indexOfArray": []string{"$categories.category_name", "entertainment"}}}}}).One(&resp)

//проекция возвращает такую структуру  map[matchedIndex:0], где 0 соответсвующий индекс элемента
//Создаем тип для проекции
var index map[string]int

//Преобразуем пустой интерфейс в тип данных предоставляемый нашей проекцией
byteData, _ := json.Marshal(resp)
err = json.Unmarshal(byteData, &index)

//Преобразовываем индекс в строку
i := strconv.Itoa(int(index["matchedIndex"]))

//Выбираем документ и устанавливаем на него курсор.
colQuerier := bson.M{"user_id": user_id, "categories." + i + ".tags": bson.M{"$elemMatch": bson.M{"list_name": "tvshow"}}}
change := bson.M{"$set": bson.M{ "categories." + i + ".tags.$.list_name": "serials"}}

//Изменяем данные
err = c.Update(colQuerier, change)

Maybe my way will help someone

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question