9

我有一个这样注释的pojo:

@Document
class Car {

  @Id
  String id ;

  @Indexed
  String manufacturer ;

}

MongoTemplate用来插入mongo。如果我在不指定集合名称的情况下插入,一切正常。但是,如果我指定一个集合名称,则不会创建除_id一个之外的任何索引。

我真的需要能够手动指定集合名称,因为:

  • 我需要确保不同的子类Car最终出现在同一个集合中
  • 我想将每年的价值存储Cars在一个单独的集合中

我必须ensureIndex()手动调用自己吗?@Indexed如果是这样,有没有办法使用我的注释来做到这一点?我要保存的实际对象比“汽车”复杂得多

4

4 回答 4

5

不幸的MongoTemplate功能

public void insert(Object objectToSave, String collectionName)

仅用于collectionName保存对象而不用于创建任何带注释的索引。如果对象传递给保存操作,则应用程序事件侦听器MongoPersistentEntityIndexCreator扫描保存的实体类以获取@Indexed注释并创建索引。但它根据下一个公式(来自来源)检测集合名称:

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

注释和注释的index.collection()集合在哪里。@Indexedentity.getCollection()@Document

因此,您需要ensureIndex()手动调用。这是奇怪的行为。我想你可以在这里打开错误:DATAMONGO

编辑: 我认为您可以创建返回所有带有注释的类的函数,@Document还可以从 mongodb 中获取所有集合cars.<year>。然后,您可以分析所有带有注释的字段@Indexed,结果,ensureIndex使用集合列表调用此字段。

于 2013-08-03T09:59:56.023 回答
2

我真的需要能够手动指定集合名称,因为:

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注释的帮助下自动创建的。

于 2013-08-03T18:27:24.503 回答
0

您最好弯腰到数据库级别并使用getIndexes检查集合是否具有您需要的索引,并在应用程序启动时调用 ensureIndex。

提示:在为您的应用程序配置 mongo 的类上实现 InitializingBean 并在那里发挥作用。

没有说教,恕我直言,Spring擅长某些事情,而在其他事情上则马马虎虎。除了在非 XA 环境中的 DI 和 TXN 管理之外,我尽量避免臃肿。

于 2013-08-08T04:56:49.560 回答
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());
    }
}
于 2017-02-23T22:57:02.120 回答