2013-07-29 14 views
6

Ich habe eine pojo wie folgt kommentierte:@Indexed Anmerkung ignoriert, wenn benannte Sammlungen mit

@Document 
class Car { 

    @Id 
    String id ; 

    @Indexed 
    String manufacturer ; 

} 

Und ich bin mit MongoTemplate in Mongo einzufügen. Wenn ich ohne Angabe eines Sammlungsnamens einfüge, funktioniert alles einwandfrei. Wenn ich jedoch einen Auflistungsnamen angeben, wird keiner der Indizes außer dem _id erstellt.

Ich muss in der Lage, wirklich den Namen der Sammlung manuell angeben, weil:

  • ich verschiedene Unterklassen von Car Ende nach oben in der gleichen Sammlung gewährleisten müssen
  • Ich möchte jedes Jahr speichern, im Wert von Cars in einer separaten Sammlung

muss ich mich ensureIndex() manuell verlangen? Wenn ja, gibt es eine Möglichkeit, meine @Indexed Annotationen zu verwenden? Die tatsächlichen Objekte Ich versuche, sind komplexer viel zu retten, als ‚Car‘

+0

ähnliche Frage http zu erstellen://stackoverflow.com/questions/23942469/create-index-in-correct-collection – Alex

Antwort

4

Leider MongoTemplate Funktion

public void insert(Object objectToSave, String collectionName) 

mit collectionName nur für Objekt speichern und nicht für alle kommentierten Indizes zu erstellen. Wenn das Objekt zum Speichern übergeben wurde, dann wird der Anwendungsereignis-Listener MongoPersistentEntityIndexCreator die gespeicherte Entitätsklasse nach @Indexed Anmerkungen durchsuchen und Indizes erstellen. Aber es Kollektionsnamen basierend auf der nächsten Formel (aus Quellen) erkennen:

String collection = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection(); 

wo index.collection() ist eine Sammlung von @Indexed Annotation und entity.getCollection() von @Document Anmerkung.

So müssen Sie ensureIndex() manuell aufrufen. Es ist seltsames Verhalten. Ich glaube, Sie Fehler hier öffnen: DATAMONGO

EDIT: Ich glaube, Sie Funktion erstellen können, die alle Klassen zurückkehren kommentierten mit @Document und erhalten auch alle Sammlungen von mongodb von cars.<year> gestartet. Anschließend können Sie alle mit @Indexed annotierten Felder analysieren und als Ergebnis ensureIndex für diese Felder mit Sammlungsliste aufrufen.

+0

@Dave: siehe Mai Zusatz zu beantworten –

1

ich den Namen der Sammlung angeben müssen in der Lage sein, um manuell wirklich da:

@Document(collection="cars") 
class Car { 

    @Id 
    String id ; 

    @Indexed 
    String manufacturer ; 

} 

@Document(collection="cars") 
class Honda extends Car { 

} 

@Document(collection="cars") 
class Volvo extends Car { 

} 
:

I need to ensure different subclasses of Car end up in the same collection 
I would like to store each year's worth of Cars in a separate collection 

Was Ihre erste Aussage, Sie eine einzelne Sammlung mit @Document Metadaten Annotation erzwingen können

Das Sammlungsfeld von @Document wird dafür sorgen, dass jede Unterklasse des Autos in die Autosammlung kommt, plus Der Index wird automatisch mit Hilfe der Annotation @Indexed erstellt.

+0

Das wäre in Ordnung, außer, wie Sie sagen, es hilft mir nicht mit dem zweiten Punkt = ( – Dave

+0

Ich habe deinen zweiten Punkt nicht verstanden. Bitte geben Sie ein Beispiel –

+0

Sicher Sache. Ich bin mir nicht sicher, wie weit verbreitet dieser Anwendungsfall ist, aber für mich ist es sehr sinnvoll, für jeden meiner Kunden völlig getrennte Sammlungen zu unterhalten. Das eigentliche Objekt, das ich speichere, ist ein Tweet (kein Auto), und für jeden Kunden sammle ich Hunderttausende Tweets. Für jeden Tweet füge ich verschiedene Anmerkungen für jeden Kunden bei. Also, wenn sie alle in einer Sammlung sind, kann es riesig werden, und ich muss viele zusätzliche Felder hinzufügen, um zu verfolgen, welcher Kunde sich um den Tweet und die Anmerkungen darauf gekümmert hat. Eine Sammlung = unordentlich, mehrere Sammlungen = sauber. – Dave

0

Sie können besser auf DB-Ebene gehen und prüfen, ob die Sammlung Indizes hat, die Sie benötigen, indem Sie getIndexes verwenden und den securityIndex als Teil Ihrer Anwendung starten.

Tipp: Implementieren Sie InitializingBean für die Klasse, die Mongo für Ihre Anwendung konfiguriert und die Magie dort tun.

Kein Predigen, IMHO Frühling ist gut in bestimmten Dingen und so-so in anderen. Ich versuche, die Aufblähung anders als für DI & TXN Management in Nicht-XA-Umgebungen zu vermeiden.

0

Nach einer langen Suche, ich denke, dass jetzt nicht möglich ist, Anmerkungen zu verwenden, so erstellte ich eine programmatische Möglichkeit, dieses Szenario zu verwalten.

Schaffung normaler Index und Verbundindex

Zuerst habe ich ein Objekt definiert, um die Indexstruktur abzubilden.

public class CollectionDefinition { 

private String id; 
private String collectionName; 
private LinkedHashMap<String, Sort.Direction> normalIndexMap; 
private ArrayList<String> compoundIndexMap; 

public String getId() { 
    return id; 
} 

public void setId(String id) { 
    this.id = id; 
} 

public String getCollectionName() { 
    return collectionName; 
} 

public void setCollectionName(String collectionName) { 
    this.collectionName = collectionName; 
} 

public LinkedHashMap<String, Sort.Direction> getNormalIndexMap() { 
    return normalIndexMap; 
} 

public void setNormalIndexMap(LinkedHashMap<String, Sort.Direction> normalIndexMap) { 
    this.normalIndexMap = normalIndexMap; 
} 

public ArrayList<String> getCompoundIndexMap() { 
    return compoundIndexMap; 
} 

public void setCompoundIndexMap(ArrayList<String> compoundIndexMap) { 
    this.compoundIndexMap = compoundIndexMap; 
} 

Die Json Sammlung wie dies

{ 
"collectionName" : "example", 
"normalIndexMap" : { 
    "sessionId" : "ASC", 
    "hash" : "DESC" 
}, 
"compoundIndexMap" : [ 
    "{\"hash\":1,\"sessionId\":1,\"serverDate\":-1}", 
    "{\"sessionId\":1,\"serverDate\":-1}", 
    "{\"sessionId\":1,\"loginWasSuccessful\":1,\"loginDate\":-1}" 
]} 

aussehen wird, dann können wir die Sammlung erstellen und die Indizes

private List<IndexDefinition> createIndexList(Map<String, Sort.Direction> normalIndexMap) { 
    Set<String> keySet = normalIndexMap.keySet(); 
    List<IndexDefinition> indexArray = new ArrayList<>(); 
    for (String key : keySet) { 
     indexArray.add(new Index(key, normalIndexMap.get(key)).background()); 
    } 
    return indexArray; 
} 

Die resultierende einzelne Indexliste kann verwendet werden, um einzelnen Feldindex zu erstellen

private void createIndexes(List<IndexDefinition> indexDefinitionList, MongoOperations mongoOperations, String collectionName) { 
    indexDefinitionList.forEach(indexDefinition -> mongoOperations.indexOps(collectionName).ensureIndex(indexDefinition)); 
} 

Die Verbindung Index oder Mehrfeldindex ist schwierig, brauchen wir DBObjects erstellen Den Index kann

private List<DBObject> createCompountIndexList(List<String> compoundIndexStringMapList) {//NOSONAR IS IN USE 
    if (compoundIndexStringMapList == null || compoundIndexStringMapList.isEmpty()) 
     return new ArrayList<>(); //NOSONAR 
    ObjectMapper mapper = new ObjectMapper(); 
    List<DBObject> basicDBObjectList = new ArrayList<>(); 
    for (String stringMapList : compoundIndexStringMapList) { 
     LinkedHashMap<String, Integer> parsedMap; 
     try { 
      parsedMap = mapper.readValue(stringMapList, new TypeReference<Map<String, Integer>>() { 
      }); 
      BasicDBObjectBuilder dbObjectBuilder = BasicDBObjectBuilder.start(); 
      Iterator it = parsedMap.entrySet().iterator(); 
      while (it.hasNext()) { 
       Map.Entry indexElement = (Map.Entry) it.next(); 
       dbObjectBuilder.add((String) indexElement.getKey(), indexElement.getValue()); 
       it.remove(); // avoids a ConcurrentModificationException 
      } 
      basicDBObjectList.add(dbObjectBuilder.get()); 
     } catch (IOException e) {//NOSONAR I´m logging it, we can not do anything more here cause it is part of the db configuration settings that need to be correct 
      Logger.getLogger(JsonCollectionCreation.class).error("The compound index definition " + stringMapList + " is not correct it can not be mapped to LinkHashMap"); 
     } 

    } 
    return basicDBObjectList; 
} 

Und das Ergebnis festgelegt werden, um den Index in der Sammlung

private void createCompoundIndex(List<DBObject> compoundIndexList, MongoOperations mongoOperations, String collectionName) { 
    if (compoundIndexList.isEmpty()) return; 
    for (DBObject compoundIndexDefinition : compoundIndexList) { 
     mongoOperations.indexOps(collectionName).ensureIndex(new CompoundIndexDefinition(compoundIndexDefinition).background()); 
    } 
} 
Verwandte Themen