2013-07-29 2 views
6

У меня есть POJO аннотированный как это:@Indexed аннотацию игнорируется при использовании именованных коллекций

@Document 
class Car { 

    @Id 
    String id ; 

    @Indexed 
    String manufacturer ; 

} 

И я использую MongoTemplate для вставки в Монго. Если я вставляю без указания имени коллекции, все работает нормально. Однако, если я укажу имя коллекции, ни один из индексов не создается, кроме _id.

мне действительно нужно, чтобы иметь возможность указать имя коллекции вручную, так как:

  • Мне нужно, чтобы обеспечить различные подклассы Car в конечном итоге в той же коллекции
  • Я хотел бы сохранить ценность каждого года по Cars в отдельной коллекции

Должен ли я позвонить ensureIndex() самостоятельно? Если да, есть ли способ сделать это, который использует мои аннотации @Indexed? Фактические объекты Я пытаюсь сохранить намного более сложным, чем «Автомобиль»

+0

Похожий вопрос HTTP://stackoverflow.com/questions/23942469/create-index-in-correct-collection – Alex

ответ

4

К сожалению MongoTemplate функции

public void insert(Object objectToSave, String collectionName) 

использованием collectionName только для сохранения объекта, а не для создания каких-либо аннотированные индексов. Если объект передан для сохранения операции, то приёмник событий приложения MongoPersistentEntityIndexCreator сканирует сохраненный класс сущности для @Indexed аннотаций и создает индексы. Но обнаружить имя коллекции на основе следующей формулы (из источников):

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

где index.collection() находится коллекция из @Indexed аннотацию и entity.getCollection() от @Document аннотацию.

Таким образом, вам необходимо позвонить по телефону ensureIndex() вручную. Это странное поведение. Я думаю, что вы можете открыть ошибку здесь: DATAMONGO

EDIT: Я думаю, что вы можете создать функцию, вернуть все классы аннотированные с @Document, а также получить все коллекции от MongoDB началась с cars.<year>. Затем вы можете проанализировать все поля, аннотированные с помощью @Indexed и, в результате, вызвать ensureIndex для этих полей, используя список коллекций.

+0

@Dave: см. может добавить к ответу –

1

мне действительно нужно, чтобы иметь возможность указать имя коллекции вручную, так как:

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 

Что касается вашего первого заявления, вы можете применять единую коллекцию с помощью аннотаций @Document метаданных:

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

} 

Поле сбора @Document позаботится о том, чтобы каждый подкласс автомобиля попадал в коллекцию автомобилей, плюс индекс автоматически создается с помощью аннотации @Indexed.

+0

Это было бы хорошо, за исключением, как вы говорите, это не помогает мне со второй точкой = ( – Dave

+0

Я не понял ваш второй пункт. Приведите пример –

+0

Несомненно. Не уверен, насколько широко распространен этот прецедент, но для меня имеет смысл поддерживать полностью отдельные коллекции для каждого моего клиента. Фактический объект, который я храню, - это твит (а не автомобиль), и для каждого клиента я могу собрать сотни тысяч твитов. Для каждого твита я буду прикладывать разные аннотации для каждого клиента. Итак, если они все в одной коллекции, она может стать огромной, и я должен добавить много дополнительных полей, чтобы отслеживать, какой клиент заботился о твите и аннотации на нем. Одна коллекция = messy, несколько коллекций = clean. – Dave

0

Возможно, вам лучше подойти к уровню БД и проверить, нужны ли вам индексы, используя getIndexes и вызывая makeIndex как часть запуска вашего приложения.

Совет: Внесите InitializingBean в класс, который настраивает mongo для вашего приложения и делает магию там.

Никакой проповеди, ИМХО Весна хороша в определенных вещах и так далее. Я стараюсь избегать раздувания, кроме DI & Управление TXN в средах, отличных от XA.

0

После длительного поиска, я думаю, что на данный момент это невозможно с помощью аннотаций, поэтому я создал программный способ управления этим сценарием.

создавая нормальный индекс и соединение индексировать

Сначала я определил объект, чтобы сопоставить структуру индекса.

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

Коллекция Json будет выглядеть следующим образом

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

Затем мы можем создать коллекцию и индексы

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

В результате один список индекса может быть использован для создания единого индекса поля

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

Индекс соединения или многопрофильное индекс сложно, нам нужно создать DBObjects определить индекс

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

И результат может быть использован для создания индекса в коллекции

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()); 
    } 
} 
Смежные вопросы