MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

MongoDB $arrayToObject


No MongoDB, o $arrayToObject operador de pipeline de agregação converte uma matriz em um documento.

A matriz fornecida para $arrayToObject deve estar em um dos dois formatos a seguir:
  • Uma matriz de matrizes de dois elementos em que o primeiro elemento é o nome do campo e o segundo elemento é o valor do campo.
  • Uma matriz de documentos que contém um k campo e um v campo, onde o k campo contém o nome do campo e o v campo contém o valor.

Formato 1


Suponha que tenhamos uma coleção chamada test com o seguinte documento:
{
	"_id" : 1,
	"data" : [
		[
			"name",
			"Fetch"
		],
		[
			"type",
			"Dog"
		]
	]
}

Podemos usar o $arrayToObject operador para retornar os data campo como um objeto de documento:
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
{ "result" : { "name" : "Fetch", "type" : "Dog" } }

Formato 2


Suponha que temos um documento como este:
{
	"_id" : 2,
	"data" : [
		{
			"k" : "name",
			"v" : "Fetch"
		},
		{
			"k" : "type",
			"v" : "Dog"
		}
	]
}

Neste caso, o k os campos contêm as chaves e o v campos contêm os valores.

Veja o que acontece quando aplicamos $arrayToObject a esse documento:
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 2 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
{ "result" : { "name" : "Fetch", "type" : "Dog" } }

Podemos ver que isso resultou no mesmo documento que foi produzido no exemplo anterior.

Matrizes não conformes


O argumento fornecido para $arrayToObject pode ser qualquer expressão válida desde que resolva para um array de arrays de dois elementos ou array de documentos que contenha k e v Campos.

Se o argumento não aderir a isso, ocorrerá um erro.

Suponha que temos o seguinte documento:
{ "_id" : 3, "data" : [ [ "name", "Fetch", "Dog" ] ] }

Esta matriz contém três elementos.

Veja o que acontece quando aplicamos $arrayToObject a esse documento:
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 3 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$arrayToObject requires an array of size 2 arrays,found array of size: 3",
	"code" : 40397,
	"codeName" : "Location40397"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Como o erro indica, $arrayToObject requires an array of size 2 arrays .

Aqui está outro documento que contém uma matriz não conforme:
{ "_id" : 4, "data" : [ { "a" : "name", "b" : "Fetch" } ] }

Neste caso, o documento dentro do array usa a e b campos em vez de k e v .

Veja o que acontece quando aplicamos $arrayToObject :
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 4 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$arrayToObject requires an object with keys 'k' and 'v'. Missing either or both keys from: {a: \"name\", b: \"Fetch\"}",
	"code" : 40393,
	"codeName" : "Location40393"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Nesse caso, o erro informa que $arrayToObject requires an object with keys 'k' and 'v' .

Tipo errado


Da mesma forma, se o argumento não for nem mesmo uma matriz, ocorrerá um erro.

Suponha que temos o seguinte documento:
{ "_id" : 5, "data" : "None" }

Os data campo contém uma string.

Veja o que acontece quando aplicamos $arrayToObject a esse documento:
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 5 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$arrayToObject requires an array input, found: string",
	"code" : 40386,
	"codeName" : "Location40386"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Como o erro indica, $arrayToObject requires an array input .

Valores nulos


Fornecendo null resulta em null .

Suponha que temos o seguinte documento:
{ "_id" : 6, "data" : null }

E aplicamos $arrayToObject :
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 6 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
{ "result" : null }

Campos ausentes


Se o campo estiver ausente, o resultado será null .

Suponha que temos o seguinte documento:
{ "_id" : 7 }

E aplicamos $arrayToObject :
db.test.aggregate(
   [
     { $match: { _id: { $in: [ 7 ] } } },
     { $project: { 
        _id: 0,
        result: { $arrayToObject: "$data" } } 
         }
   ]
)

Resultado:
{ "result" : null }

Nomes de campo repetidos


De acordo com a documentação do MongoDB, se o nome de um campo se repetir no array:
  • A partir da versão 4.0.5, $arrayToObject usa o último valor para esse campo. Para 4.0.0-4.0.4, o valor usado depende do driver.
  • A partir da versão 3.6.10, $arrayToObject usa o último valor para esse campo. Para 3.6.0-3.6.9, o valor usado depende do driver.
  • A partir da versão 3.4.19, $arrayToObject usa o último valor para esse campo. Para 3.4.0-3.4.19, o valor usado depende do driver.