@zebox

Редактирование и удаление элементов вложенного массива в MongoDB на Go?

Всем привет!
Народ подскажите как реализовать операции (редактирование\удаление) с элементами вложенного в документ массива?
Структура документа:
{
"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"]
						}
					]
			}
  ]
}


С добавлением и проверкой на уникальность разобрался, а вот с удалением и редактированием не могу понять как сделать. Например, нужно отредактровать list_name=summer на sum в категории sport или удалить элемент list_name=tvshow из категории entertainment.

Удаление пытаюсь делать таким образом:

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)


Но удаление не срабатывает.
MongoDB v. 3.4

Как реализовать редактирование пока не могу понять...

Помогите разобраться.
  • Вопрос задан
  • 625 просмотров
Решения вопроса 1
@zebox Автор вопроса
Вопрос решен!
Возможно через костыль (т.к. наверное можно было реализовать через $map или $filter), но в итоге все работает как нужно.

Удаление:
//выбираем документ и устанавливаем на него курсор.
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)


Редактироваие:
Т.к. оператор "$" можно использовать только для одного массива, то необходимо изначально найти индекс основного массива, а после выполнить запрос с явным указанием индекса элемента для выборки вложенного документа (массива).

//создаем пустой интерфейс для получения данных агрегации
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)


Может мой способ кому-то поможет
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы