sql >> Databasteknik >  >> NoSQL >> MongoDB

Spring Data Mongo - tillämpa unika kombinationsfält i inbäddade dokument

I MongoDB säkerställer ett unikt index att ett visst värde i ett fält inte finns i mer än ett dokument. Det kommer inte garantera att ett värde är unikt över en array i ett enda dokument. Detta förklaras här i MongoDB-manualen där det diskuteras unika multikey-index.

Således kommer ett unikt index inte att uppfylla ditt krav. Det kommer att förhindra att separata dokument innehåller dubbletter av kombinationer, men det kommer fortfarande att tillåta ett enstaka dokument att innehålla dubbletter av värden över en array.

Det bästa alternativet du har är att ändra din datamodell för att dela upp arrayen av technologyEmployeeRef-objekt i separata dokument. Om du delar upp det i separata dokument kan du använda ett unikt index för att framtvinga unikhet.

Den specifika implementeringen som bör tas för denna datamodelländring beror på ditt åtkomstmönster (vilket ligger utanför denna frågas omfattning).

Ett sådant sätt detta skulle kunna göras är att skapa en TechnologyEmployee-samling som har alla de fält som för närvarande finns i technologyEmployeeRef-arrayen. Dessutom skulle denna TechnologyEmployee-samling ha ett fält, till exempel e-post, som gör att du kan koppla den till ett dokument i Employee-samlingen.

Exempel på anställdsdokument

{
  ....
  ....
  "firstName" : "John",
  "lastName" : "Doe",
  "email" : "[email protected]",
  .....
  .....
  .....
}

Exempel på EmployeeTechnology Document

{
  "email" : "[email protected]",
  "technologyCd" : "Java",
  "technologyName" : "Java8",
  ....
  .....
  "status" : "A"
}

Index i EmployeeTechnology-samlingen

{'email' : 1, 'technologyCd' : 1}, {unique: true}

Nackdelen med detta tillvägagångssätt är att du skulle behöva läsa från två samlingar för att ha all data. Denna nackdel kanske inte är en stor sak om du sällan behöver hämta data från båda samlingarna samtidigt. Om du behöver all data kan den snabbas upp genom att använda index. Med indexen skulle det kunna påskyndas ytterligare genom att använda täckta frågor.

Ett annat alternativ är att denormalisera data. Du skulle göra detta genom att duplicera de anställdas data som du behöver komma åt samtidigt som teknikdatan.

Exempeldokument

[
  {
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "[email protected]",
    .....
    "technologyCd" : "Java",
    "technologyName" : "Java8",
    ....
    "status" : "A"
  },
  {
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "[email protected]",
    .....
    "technologyCd" : "Spring",
    "technologyName" : "Spring Boot2",
    ....
    "status" : "A"
  }
]

I detta MongoDB-blogginlägg säger de att

Du skulle bara göra detta för fält som läses ofta, läses mycket oftare än de uppdateras, och där du inte kräver stark konsistens, eftersom uppdatering av ett denormaliserat värde är långsammare, dyrare och inte är atomärt.

Eller som du redan har nämnt, det kan vara vettigt att lämna datamodellen som den är och att utföra kontrollen för unikhet på applikationssidan. Detta kan sannolikt ge dig den bästa läsprestandan, men det har vissa nackdelar. För det första kommer det att sakta ner skrivoperationerna eftersom programmet måste köra några kontroller innan det kan uppdatera databasen.

Det kan vara osannolikt, men det finns också en möjlighet att du fortfarande kan sluta med dubbletter. Om det finns två back-to-back-förfrågningar för att infoga samma EmployeeTechnology-objekt i arrayen, kan valideringen av den andra begäran avslutas (och passera) innan den första begäran har skrivits till databasen. Jag har själv sett ett liknande scenario med en applikation jag arbetat på. Även om applikationen letade efter unika, om en användare dubbelklickade på en skicka-knapp skulle det sluta med dubbla poster i databasen. I det här fallet minskade risken drastiskt att inaktivera knappen vid det första klicket. Denna lilla risk kan tolereras, beroende på dina krav och effekterna av att ha dubbla poster.

Vilket tillvägagångssätt som är mest meningsfullt beror till stor del på ditt åtkomstmönster och krav. Hoppas detta hjälper.




  1. Redis med Resque och Rails:ERR-kommando tillåts inte när minne> 'maxmemory' används

  2. 2 sätt att ta bort en databas i MongoDB

  3. mongoDB :Skapa ett objekt-ID för varje nytt barn som läggs till i matrisfältet

  4. Rate-Limit an API (spring MVC)