2013-07-29 12 views
6

Mam POJO uwagami tak:@Indexed adnotacja ignorowane przy użyciu nazwanych zbiorów

@Document 
class Car { 

    @Id 
    String id ; 

    @Indexed 
    String manufacturer ; 

} 

i używam MongoTemplate wstawić do Mongo. Jeśli wstawię bez podania nazwy kolekcji, wszystko działa poprawnie. Jeśli jednak podam nazwę kolekcji, żaden z indeksów nie zostanie utworzony z wyjątkiem _id.

Naprawdę muszę być w stanie podać nazwę kolekcji ręcznie, ponieważ:

  • muszę zapewnić różne podklasy Car kończy się w tej samej kolekcji
  • Chciałbym zapisać każdy rok o wartości Cars w oddzielnej kolekcji

Czy muszę zadzwonić pod numer ensureIndex() ręcznie? Jeśli tak, czy jest jakiś sposób, aby to zrobić, korzystając z adnotacji @Indexed? Rzeczywiste obiekty Próbuję zapisać są dużo bardziej skomplikowane niż „Car”

+0

Podobne pytanie http://stackoverflow.com/questions/23942469/create-index-in-correct-collection – Alex

Odpowiedz

4

Niestety MongoTemplate funkcji

public void insert(Object objectToSave, String collectionName) 

użyciu collectionName tylko do zapisywania obiektu, a nie do tworzenia jakichkolwiek adnotacją indeksów. Jeśli obiekt został przekazany do operacji zapisywania, wówczas detektor zdarzeń aplikacji MongoPersistentEntityIndexCreator skanuje zapisaną klasę obiektu dla @Indexed adnotacji i tworzy indeksy. Ale to wykryć nazwę kolekcji na podstawie kolejnego wzoru (ze źródeł):

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

gdzie index.collection() jest kolekcja z @Indexed adnotacji i entity.getCollection() od @Document adnotacji.

Musisz więc ręcznie zadzwonić pod numer ensureIndex(). To dziwne zachowanie. Myślę, że można otworzyć bug tutaj: DATAMONGO

EDIT: myślę, że można utworzyć funkcję powrotu wszystkich klas adnotacją z @Document a także uzyskać wszystkie zbiory z MongoDB rozpoczął od cars.<year>. Następnie możesz analizować wszystkie pola opatrzone komentarzem: @Indexed, a następnie wywołać ensureIndex dla tych pól przy użyciu listy kolekcji.

+0

@Dave: patrz dodatek maja, aby odpowiedzieć –

1

naprawdę potrzebne, aby móc ręcznie określić nazwę kolekcji, ponieważ:

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 

Co do pierwszego rachunku, można wymusić jednej kolekcji za pomocą adnotacji @Document metadanych:

@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 { 

} 

Pole zbiórki @Document zadba o to, aby każda podklasa samochodu trafiła do kolekcji samochodów plus indeks jest tworzony automatycznie za pomocą adnotacji @Indexed.

+0

to byłoby w porządku z wyjątkiem, jak mówisz, to nie może mi pomóc z drugiego punktu = ( – Dave

+0

Nie zrozumiałem twojego drugiego punktu. Proszę podać przykład: –

+0

Pewnie. Nie jestem pewien, jak szeroki jest ten przypadek użycia, ale dla mnie ma sens utrzymanie całkowicie odrębnych kolekcji dla każdego mojego klienta. Rzeczywistym obiektem, który przechowuję jest tweet (nie samochód), a dla każdego klienta mogę zebrać setki tysięcy tweetów. Do każdego tweeta dołączam różne adnotacje dla każdego klienta. Tak więc, jeśli wszystkie są w jednej kolekcji, może stać się ogromna i muszę dodać wiele dodatkowych pól, aby śledzić, który klient dbał o tweet i adnotacje na nim. Jedna kolekcja = bałagan, wiele kolekcji = czyste. – Dave

0

Być może lepiej odejść do poziomu DB i sprawdzić, czy kolekcja ma indeksy, których potrzebujesz, używając getIndexes i wywoływać metodę ensureIndex w ramach uruchamiania aplikacji.

Wskazówka: Wdrożenie InitializingBean od klasy, który konfiguruje Mongo dla aplikacji i zrobić tam magię.

Nie głoszenie, IMHO Wiosna to dobry na pewne rzeczy i tak więc w innych. Próbuję uniknąć nadmiaru innego niż w przypadku DI & Zarządzanie TXN w środowiskach innych niż XA.

0

Po długich poszukiwaniach, myślę, że na razie nie jest posible użyciu adnotacji, więc stworzyłem programowo sposób zarządzać ten scenariusz.

tworzenia prawidłową indeks i związek indeks

Najpierw definiowany przez obiekt mapowania struktury indeksu.

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; 
} 

Kolekcja Json będzie wyglądać następująco

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

wtedy możemy stworzyć kolekcję i indeksy

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; 
} 

Lista wynikające pojedynczy indeks może być wykorzystywane do tworzenia jednolitego indeksu pola

Indeks związek lub indeks multifield jest trudne, musimy stworzyć DBObjects zdefiniować indeks

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; 
} 

A wynik może być wykorzystywane do tworzenia indeksu w kolekcji

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()); 
    } 
}