MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB $ unisci oggetti

In MongoDB, il $mergeObjects l'operatore della pipeline di aggregazione combina più documenti in un unico documento.

Sintassi

Il $mergeObjects operatore supporta due sintassi.

Sintassi 1:

{ $mergeObjects: [ <document1>, <document2>, ... ] }

Sintassi 2:

{ $mergeObjects: <document> }

La prima sintassi accetta più argomenti e la seconda sintassi accetta un argomento.

Esempio di sintassi 1 (argomenti multipli)

La prima sintassi prevede di fornire $mergeObjects con più di un argomento/documento. $mergeObjects quindi combina quei documenti in uno solo.

Supponiamo di avere una collezione chiamata users con il seguente documento:

{
	"_id" : 1,
	"name" : {
		"f_name" : "Homer",
		"l_name" : "Simpson"
	},
	"contact" : {
		"email" : "[email protected]",
		"ph" : null
	}
}

Possiamo usare $mergeObjects per unire il name e contact campi:

db.users.aggregate(
  [
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$contact" ] }
        }
    }
  ]
).pretty()

Risultato:

{
	"_id" : 1,
	"user" : {
		"f_name" : "Homer",
		"l_name" : "Simpson",
		"email" : "[email protected]",
		"ph" : null
	}
}

In questo caso, abbiamo unito entrambi i campi in un unico campo chiamato user . Se avessimo avuto più campi/documenti avremmo potuto unire anche quelli se lo avessimo voluto.

Nomi campi duplicati

Se i documenti da unire contengono nomi di campo duplicati, $mergeObjects sovrascrive il campo mentre unisce i documenti. Pertanto, il campo nel documento risultante contiene il valore dell'ultimo documento unito per quel campo.

Supponiamo di avere il seguente documento:

{
	"_id" : 2,
	"name" : {
		"f_name" : "Peter",
		"l_name" : "Griffin"
	},
	"contact" : {
		"email" : "[email protected]",
		"f_name" : "Bart"
	}
}

Possiamo vedere che entrambi i documenti contengono un campo chiamato f_name .

Ecco cosa succede quando uniamo quei documenti:

db.users.aggregate(
  [
    { $match: { _id: 2 } },
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$contact" ] }
        }
    }
  ]
).pretty()

Risultato:

{
	"_id" : 2,
	"user" : {
		"f_name" : "Bart",
		"l_name" : "Griffin",
		"email" : "[email protected]"
	}
}

Il f_name il campo nel documento risultante contiene Bart , che è il valore dell'ultimo documento unito.

Valori Nulli

Se si unisce un documento con null , il documento risultante verrà restituito senza alcuna modifica.

Ma se tutti i documenti da unire sono null , viene restituito un documento vuoto.

Supponiamo di avere i seguenti documenti:

{
	"_id" : 3,
	"name" : {
		"f_name" : "Hubert",
		"l_name" : "Farnsworth"
	},
	"contact" : null
}
{ "_id" : 4, "name" : null, "contact" : null }

Ecco cosa succede quando uniamo il name e contact campi in questi due documenti:

db.users.aggregate(
  [
    { $match: { _id: { $in: [ 3, 4 ] } } },
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$contact" ] }
        }
    }
  ]
)

Risultato:

{ "_id" : 3, "user" : { "f_name" : "Hubert", "l_name" : "Farnsworth" } }
{ "_id" : 4, "user" : {  } }

Esempi di sintassi 2 (argomento singolo)

Di seguito sono riportati due esempi che utilizzano la sintassi dell'argomento singolo.

$group Accumulatore di stadi

Nel primo esempio, $mergeObjects è usato come $group accumulatore di stadi.

Supponiamo di avere una collezione chiamata products con i seguenti documenti:

{
	"_id" : 1,
	"product" : "Shirt",
	"inventory" : {
		"blue" : 10,
		"red" : 2
	}
}
{
	"_id" : 2,
	"product" : "Shirt",
	"inventory" : {
		"green" : 3,
		"black" : 1
	}
}
{
	"_id" : 3,
	"product" : "Shorts",
	"inventory" : {
		"blue" : 2,
		"red" : 8
	}
}
{
	"_id" : 4,
	"product" : "Shorts",
	"inventory" : {
		"green" : 5,
		"black" : 3
	}
}

Possiamo raggruppare questi documenti in base al loro product campo, quindi utilizzare $mergeObjects per unire l'inventory campo per ogni gruppo:

db.products.aggregate( [
   { $group: { 
     _id: "$product", 
     mergedProducts: { $mergeObjects: "$inventory" } 
     } 
    }
]).pretty()

Risultato:

{
	"_id" : "Shorts",
	"mergedProducts" : {
		"blue" : 2,
		"red" : 8,
		"green" : 5,
		"black" : 3
	}
}
{
	"_id" : "Shirt",
	"mergedProducts" : {
		"blue" : 10,
		"red" : 2,
		"green" : 3,
		"black" : 1
	}
}

Array

Questo esempio applica $mergeObjects a un singolo documento che contiene un campo con una matrice di documenti.

Supponiamo di avere una collezione chiamata test con i seguenti documenti:

{
	"_id" : 1,
	"data" : [
		{
			"a" : 1,
			"b" : 2
		},
		{
			"c" : 3,
			"d" : 4
		}
	]
}

Possiamo applicare $mergeObjects ai data campo:

db.test.aggregate(
  [
    {
      $project:
        { 
          result: { $mergeObjects: "$data" }
        }
    }
  ]
)

Risultato:

{ "_id" : 1, "result" : { "a" : 1, "b" : 2, "c" : 3, "d" : 4 } }

Campi mancanti

$mergeObjects ignora tutti i campi mancanti. Cioè, se fornisci un campo che non esiste, lo ignora. Se nessuno dei campi esiste, restituisce un documento vuoto.

Esempio:

db.users.aggregate(
  [
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$oops" ] }
        }
    }
  ]
).pretty()

Risultato:

{ "_id" : 1, "user" : { "f_name" : "Homer", "l_name" : "Simpson" } }
{ "_id" : 2, "user" : { "f_name" : "Peter", "l_name" : "Griffin" } }
{ "_id" : 3, "user" : { "f_name" : "Hubert", "l_name" : "Farnsworth" } }
{ "_id" : 4, "user" : { } }

Tuttavia, ecco cosa succede quando nessuno dei campi esistono:

db.users.aggregate(
  [
    {
      $project:
        { 
          user: { $mergeObjects: [ "$wrong", "$oops" ] }
        }
    }
  ]
).pretty()

Risultato:

{ "_id" : 1, "user" : { } }
{ "_id" : 2, "user" : { } }
{ "_id" : 3, "user" : { } }
{ "_id" : 4, "user" : { } }

Il risultato è un documento vuoto.

È lo stesso quando si utilizza la sintassi a argomento singolo.

Esempio:

db.products.aggregate( [
   { $group: { 
     _id: "$product", 
     mergedProducts: { $mergeObjects: "$oops!" } 
     } 
    }
]).pretty()

Risultato:

{ "_id" : "Shorts", "mergedProducts" : { } }
{ "_id" : "Shirt", "mergedProducts" : { } }