Hvis jeg i det væsentlige forstår din essens, vil du grundlæggende have det
- Træk det element, der ikke er påkrævet, fra dit referencearray
- Indstil værdien af dit hovedreferencefelt til det første element i det ændrede array
Og få det gjort alt i én opdatering uden at flytte dokumenter henover ledningen.
Men dette kan desværre ikke lade sig gøre. Hovedproblemet med dette er, at der ikke er nogen måde at henvise til værdien af et andet felt i dokumentet, der opdateres. Alligevel skal du for at gøre dette uden at gentage også få adgang til ændret array for at få det nye første element.
Måske er en tilgang at genoverveje dit skema for at opnå det, du ønsker. Min mulighed her ville udvide dine referencedokumenter lidt og fjerne behovet for hovedreferencefeltet.
Det ser ud til, at den antagelse, du er villig til at leve med på opdateringerne, er, at hvis den fjernede reference var hovedreferencen, så kan du bare indstille den nye hovedreference til det første element i arrayet. Med det i tankerne skal du overveje følgende struktur:
refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ]
Ved at ændre disse til dokumenter med en oid
egenskab, der ville blive sat til ObjectId det giver mulighed for at have en ekstra egenskab på dokumentet, der specificerer, hvilken der er standard. Dette kan nemt forespørges bestemme hvilket Id der er hovedreferencen.
Overvej nu også, hvad der ville ske, hvis dokumentet, der matcher "object5" i oid-feltet, blev trukket fra arrayet:
refs: [ { oid: "object1" }, { oid: "object2" } ]
Så når du spørger efter, hvad er main-reference
i henhold til den tidligere logik accepterer du det første dokument i arrayet. Nu selvfølgelig til dine applikationskrav, hvis du vil indstille en anden main-reference
du ændrer blot dokumentet
refs: [ { oid: "object1" }, { oid: "object2", main: true } ]
Og nu er logikken tilbage at vælge det array-element, der har hovedegenskaben, som sand vil forekomme i præference, og som vist ovenfor, at hvis den egenskab ikke eksisterer på nogen elementer, så fald tilbage til det første element.
Med alt det fordøjet bliver din operation for at trække alle referencer til et objekt ud af det array i alle dokumenter ret enkel, som det gøres i shellen (samme format bør grundlæggende gælde for hvilken som helst driver):
db.books.update(
{ "refs.oid": "object5" },
{ $pull: { refs: {oid: "object5"} } }, false, true )
De to ekstra argumenter til forespørgslen og opdateringsoperationen er upsert
og multi
henholdsvis. I dette tilfælde upsert
giver ikke meget mening, da vi kun ønsker at ændre dokumenter, der eksisterer, og multi
betyder, at vi vil opdatere alt, der matchede. Standarden er kun at ændre det første dokument.
Naturligvis forkortede jeg al notationen, men værdierne kan selvfølgelig være faktiske ObjectId'er i henhold til din hensigt. Det virkede også rimeligt at antage, at din primære brug af main-reference
er, når du har hentet dokumentet. Definere en forespørgsel, der returnerer main-reference
ved at følge logikken der blev skitseret burde være muligt, men som det står har jeg skrevet en masse herude og skal holde pause til aftensmaden :)
Jeg tror, at dette er et værdifuldt argument for at genoverveje dit skema for at undgå over wire iterationer for det, du ønsker at opnå.