使用python和pymongo的MongoDB位置运算符索引问题

2022-03-14 00:00:00 python arrays nested mongodb pymongo

问题描述

我正在学习MongoDB,我一直在尝试更新歌曲的嵌套数组,但是,位置运算符似乎更新了错误的索引。

以下是数据库中文档的结构:

{
 '_id': ObjectId(...),
 'artistName': Artist Name,
 'recordLabel': Label Name,
 'genre': Genre,
 'albums': [
   {
     'albumName': Album 1
     'songs': [ Song 1, Song 2]
   }, 
   {
     'albumName': Album 2
     'songs': [ Song 3, Song 4]
   }, 
 ]
}

下面是我尝试执行的update_one()函数:

 artistcol.update_one(
    { 'albums.songs': 'Song 2' },
    { '$set': { 'albums.$[name].songs.$': 'Test 1' }},
    array_filters=[{ 'name.albumName': 'Album 1' }]
  )

Execute函数中的值是从表单传入的,但我只是为此POST硬编码了值。

预期:
基于上面的查询,我正在查找具有"Song 2"的对象,然后使用数组筛选器获取其所在的右侧专辑对象,然后使用位置运算符获取歌曲的索引并将值更改为"Test 1"。

如果我通过引用数据库对专辑索引和歌曲索引进行硬编码,则可以工作,但我需要它们是动态的,因为用户将选择专辑、歌曲标题,然后为歌曲提供新值。

实际:
查询完成时,"歌曲%1"已更新为"测试%1",而不是"歌曲%2"。
如果我尝试:

 artistcol.update_one(
    { 'albums.songs': 'Song 3' },
    { '$set': { 'albums.$[name].songs.$': 'Test 2' }},
    array_filters=[{ 'name.albumName': 'Album 2' }]
  )

它会将"歌曲4"更新为"测试2"。

我目前了解的:
似乎无论过滤查询找到什么索引,位置运算符($)都引用该索引。

我唯一需要弄清楚的就是如何定位歌曲中的特定数组元素,并将其值更改为用户输入的任何值。

我看了很多MongoDB的文档,尽我所能去了解,尝试了不同的方法,但是没有任何成功。

任何帮助都将不胜感激,我不知道从这里到哪里去。:)


解决方案

位置运算符将引用顶级数组中与查询匹配的第一个元素。

在问题中的查询中,$是指匹配的专辑,即

 {
     'albumName': Album 1
     'songs': [ Song 1, Song 2]
 }, 

使用数组过滤选择嵌套数组的元素,如:

.update(
  {"albums.songs": "Song 2"},
  {$set: {"albums.$.songs.$[song]": "Tested"}},
  {arrayFilters: [{song: "Song 2"}]
})

Playground

相关文章