2012-06-29 16 views
16

Ho una domanda riguardante MongoDB con Spring Data. Ho questi classi di dominio:Gli oggetti incorporati MongoDB non hanno ID (valore null)

@Document 
public class Deal { 
    @Id 
    private ObjectId _id; 
    private Location location; 
    private User user; 
    private String description; 
    private String title; 
    private String price; 
    private boolean approved; 
    private Date expirationDate; 
    private Date publishedDate; 
} 

@Document 
public class Location { 
    @Id 
    private ObjectId _id; 
    private Double latitude; 
    private Double longitude; 
    private String country; 
    private String street; 
    private String zip; 
} 

@Document 
public class User { 
    @Id 
    private ObjectId _id; 
    private String email; 
    private String password; 
    private String profile_image_url; 
    private Collection<Deal> deals = new ArrayList<Deal>(); 
} 

Con questi domini posso con successo CRUD. C'è solo un problema. Quando si salva un utente con offerte, le offerte e la posizione ottengono _id impostato su null quando li si salva in MongoDB. Perché MongoDB non può generare ID univoci per gli oggetti incorporati?

Il risultato dopo il salvataggio di un utente con un affare:

{ "_id" : ObjectId("4fed0591d17011868cf9c982"), 
    "_class" : "User", 
    "email" : "[email protected]", 
    "password" : "mimi", 
    "deals" : [ 
    { "_id" : null, 
     "location" : { "_id" : null, 
     "latitude" : 2.22, 
     "longitude" : 3.23445, 
     "country" : "Denmark", 
     "street" : "Denmark road 77", 
     "zip" : "2933" }, 
     "description" : "The new Nexus 7 Tablet. A 7 inch tablet from Google.", 
     "title" : "Nexus 7", 
     "price" : "1300", 
     "approved" : false, 
     "expirationDate" : Date(1343512800000), 
     "publishedDate" : Date(1340933521374) } ] } 

Come si può vedere dal risultato, affare e posizione ID è impostato su NULL.

+0

Un ID identifica un documento radice, non sub-documenti. Non vi è alcun motivo per cui si desideri generare automaticamente un ID per un documento nidificato in quanto MongoDB può comunque recuperare solo i documenti di livello superiore. Per cosa hai effettivamente bisogno dell'id nidificato? –

+0

Devo cercare solo offerte e non utenti. Ora devo cercare da utente e quindi il ciclo ha gettato ogni affare dell'utente a livello di programmazione. – Millad

+0

L'ID non ha nulla a che fare con ciò che è possibile cercare. È perfettamente alla ricerca di '{'deals.price': {$ gt: 1000}}'. Tuttavia, questa query restituirebbe un oggetto 'Utente' che dovresti manualmente estrarre il' Deal' da quel momento. Questa è una limitazione di MongoDB, nulla implicito da Spring Data. –

risposta

4

Un _id non è impostato su documenti secondari per impostazione predefinita solo sui documenti radice.

È necessario definire un _id per i propri documenti secondari su inserimento e aggiornamento.

+0

Non dovrebbe farlo per me? Come lo posso fare? Devo inserire ogni documento da solo e li metto insieme? Ecco come inserisco: mongoOperation.insert (deal); – Millad

+0

MongoDB non lo farà per te ma ora che ti do una seconda occhiata forse il tuo Driver dovrebbe ... stai usando Morphia? – Sammaye

+0

grazie per le risposte. Sto usando Spring Data e mongo-java-driver. Quando cerco offerte, ottengo un oggetto Utente. Non riesco a cercare utilizzando Deals Devo andare a gettare Utente e quindi interrogare programmaticamente in Utente per le offerte. – Millad

29

operazioni CRUD (MongoDB insert, update, find, remove), tutto sui documenti di alto livello esclusivamente - anche se naturalmente è possibile filtrare da campi nei documenti incorporati. I documenti incorporati vengono sempre restituiti all'interno del documento principale.

Il campo _id è un campo obbligatorio del documento principale e in genere non è necessario o è presente nei documenti incorporati. Se hai bisogno di un identificativo univoco, puoi certamente crearlo, e puoi usare il campo _id per memorizzarlo se questo è conveniente per il tuo codice o per il tuo modello mentale; più tipicamente, prendono il nome da ciò che rappresentano (ad esempio "username", "otherSystemKey", ecc.). Né MongoDB né alcuno dei driver popoleranno automaticamente un campo _id tranne nel documento di livello superiore.

In particolare in Java, se si desidera generare valori ObjectId per il campo _id nei documenti incorporato, è possibile farlo con:

someEmbeddedDoc._id = new ObjectId(); 
+0

Grazie per aver chiarito. Pertanto, se desidero elencare solo le offerte, devo separare o spostare il documento dell'utente dal documento Deal in modo che Deal sia un documento separato e User sia un documento separato e quindi esegua una query. – Millad

+0

In alternativa, o modifica il codice per lavorare con il modello dati esistente. Se si manipolano spesso offerte o se le offerte sono associate a più di un utente, la normalizzazione del modello di dati può essere sensata. – dcrosta

2

Mongo non crea o bisogno _id s sui documenti incorporati. Puoi aggiungere un campo _id se lo desideri - l'ho fatto.

@Document 
public class Location { 
    @Id 
    private ObjectId _id; 

    public Location() { 
     this._id = ObjectId.get(); 
    } 
} 

@Document 
public class User { 
    @Id 
    private ObjectId _id; 

    public User() { 
     this._id = ObjectId.get(); 
    } 
} 

Questo funziona perfettamente per me.

4

Nel contesto di un'architettura REST ha tutto il senso che i documenti nidificati hanno i propri ID.

  1. L'implementazione della persistenza deve essere indipendente dalla rappresentazione delle risorse. Come consumatore di API non mi interessa se usi mongo o mysql. Se hai un nido doc senza id in mongo prova a immaginare come cambiare il livello di persistenza in un database relazionale. Ora fai lo stesso esercizio avendo pensato in anticipo con un approccio indipendente dall'implementazione. La modellazione di documenti nidificati in documenti relazionali db, root e nidificati sarà costituita da diverse entità/tabelle ognuna con i propri id. La radice potrebbe avere una relazione uno a molti con il documento annidato.
  2. Potrebbe essere necessario accedere direttamente a un documento nidificato anziché in modo sequenziale. Potrebbero non essere necessari ID univoci assoluti, come quelli emessi da mongo, ma sarà comunque necessario un identificatore univoco locale. Questo è, unico nel doc radice.

Dopo aver discusso il mio punto sulla necessità di id in documenti annidati @dcrosta ha già dato una risposta corretta su come popolare il campo _id in mongo.

Spero che questo aiuti.

Problemi correlati