代码之家  ›  专栏  ›  技术社区  ›  santaclown

MongoDB:在由同一数组中其他字段的$concat组成的数组中添加一个字段

  •  1
  • santaclown  · 技术社区  · 2 年前

    让我首先说,我是MongoDB的新手。我几天前才开始上班。

    我有一个员工集合,其中一个字段代表电话号码分解为多个部分。它看起来是这样的:

      {
        _id: ObjectId('666225dbe02f02db7f19465a'),
        lastName: 'Smith',
        firstName: 'John',
        middleInitial: '',
        email: '[email protected]',
        phone: [
          {
            international: '',
            area: '555',
            prefix: '555',
            number: '1234',
            ext: '',
            name: 'work'
          },
          {
            international: '',
            area: '555',
            prefix: '555',
            number: '2345',
            ext: '',
            name: 'cell'
          }
        ],
        address: {
          work: {
            city: 'New York',
            province: 'NY',
            buildingName: 'Empire State Building',
            address: '20 W 34th St.',
            postalCode: '10001',
            mailstop: '49B'
          }
        },
        positionId: ObjectId('666225dbe92f02db8f09465d')
      }
    

    我试图实现的是在每个数组元素中重新组合电话号码,如下所示:

      {
    [...]
        phone: [
          {
            international: '',
            area: '555',
            prefix: '555',
            number: '1234',
            ext: '',
            name: 'work',
            phone: '(555) 555-1234'
          },
          {
            international: '',
            area: '555',
            prefix: '555',
            number: '2345',
            ext: '',
            name: 'cell',
            phone: '(555) 555-2345'
          }
        ],
    [...]
      }
    

    我使用的是PHP,所以我的代码示例将使用PHP。我试过一些东西,但这就是我现在所拥有的。

    $documents = $collection->aggregate([
      [
        '$addFields'=>[
          'phone.phone'=>[
            '$map'=>[
              'input'=> '$phone',
              'as'=> "p",
              'in'=>[
                '$concat'=>[
                  "(", '$$p.area', ") ",
                  '$$p.prefix', "-",
                  '$$p.number',
                  [
                    '$cond'=> [
                      [
                        '$ne'=>[
                          '$$p.ext',
                          ''
                        ],
                      ],
                      [
                        '$concat'=>[
                          ' ext. ',
                          '$$p.ext',
                        ],
                      ],
                      ''
                    ],
                  ],
                ],
              ],
            ],
          ],
        ],
      ],
    ]);
    
    

    不幸的是,这会返回电话数组的EACH元素中的所有电话号码的数组

      {
    [...]
        phone: [
          {
            international: '',
            area: '555',
            prefix: '555',
            number: '1234',
            ext: '',
            name: 'work',
            phone: [ '(555) 555-1234', '(555) 555-2345' ]
          },
          {
            international: '',
            area: '555',
            prefix: '555',
            number: '2345',
            ext: '',
            name: 'cell',
            phone: [ '(555) 555-1234', '(555) 555-2345' ]
          }
        ],
    [...]
      }
    

    我尝试使用$project,但我需要拥有员工的所有字段,因为并非所有员工都有相同的字段,而且项目不允许我“默认返回所有字段”,我必须指定所有字段。我还尝试了$addFields(如上所示),我尝试使用find而不是聚合,但我得到了相同的结果。我在互联网和MongoDB文档上搜索了几个小时来寻找解决方案,但找不到任何解决方案(或者不知道如何准确键入我想要的内容)。

    我知道这在PHP中可以很容易地完成,但我正在努力学习MongoDB。

    感谢您提供的任何帮助。

    1 回复  |  直到 2 年前
        1
  •  1
  •   ray    2 年前

    您的尝试导致数组字段的原因是您在整体上进行操作 phone 数组字段。你实际上正处于正确的使用轨道上 $map 以逐个迭代数组条目。你只需要使用 $mergeObjects 以执行元素操作。

    db.collection.update({},
    [
      {
        "$set": {
          "phone": {
            "$map": {
              "input": "$phone",
              "as": "p",
              "in": {
                "$mergeObjects": [
                  "$$p",
                  {
                    phone: {
                      "$concat": [
                        "(",
                        "$$p.area",
                        ") ",
                        "$$p.prefix",
                        "-",
                        "$$p.number"
                      ]
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ],
    {multi: true})
    

    Mongo Playground