2013-07-29 41 views
6

Tôi có một POJO chú thích như thế này:chú thích @Indexed bỏ qua khi sử dụng tên bộ sưu tập

@Document 
class Car { 

    @Id 
    String id ; 

    @Indexed 
    String manufacturer ; 

} 

Và tôi đang sử dụng MongoTemplate để chèn vào Mông Cổ. Nếu tôi chèn mà không chỉ định tên bộ sưu tập, mọi thứ sẽ hoạt động tốt. Tuy nhiên, nếu tôi chỉ định tên bộ sưu tập thì không có chỉ mục nào được tạo ngoại trừ _id.

tôi thực sự cần phải có khả năng xác định tên bộ sưu tập bằng tay vì:

  • tôi cần phải đảm bảo lớp con khác nhau của Car cuối lên trong bộ sưu tập cùng
  • Tôi muốn để lưu trữ giá trị của mỗi năm Cars trong bộ sưu tập riêng

Tôi có phải tự gọi ensureIndex() theo cách thủ công không? Nếu vậy, có cách nào để làm điều đó sử dụng chú thích @Indexed của tôi không? Các đối tượng thực tế tôi đang cố gắng để tiết kiệm rất nhiều phức tạp hơn so với 'xe'

+0

câu hỏi tương tự http://stackoverflow.com/questions/23942469/create-index-in-correct-collection – Alex

Trả lời

4

Thật không may MongoTemplate chức năng

public void insert(Object objectToSave, String collectionName) 

sử dụng collectionName chỉ để lưu đối tượng và không cho tạo ra bất kỳ chỉ số chú thích. Nếu đối tượng được truyền để lưu hoạt động thì trình nghe sự kiện ứng dụng MongoPersistentEntityIndexCreator quét lớp tổ chức đã lưu cho các chú thích @Indexed và tạo chỉ mục. Nhưng nó phát hiện tên bộ sưu tập dựa trên công thức tiếp theo (từ nguồn):

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

nơi index.collection() là bộ sưu tập từ @Indexed chú thích và entity.getCollection() từ @Document chú thích.

Vì vậy, bạn cần gọi ensureIndex() theo cách thủ công. Đó là hành vi kỳ lạ. Tôi nghĩ rằng bạn có thể mở lỗi ở đây: DATAMONGO

EDIT: Tôi nghĩ rằng bạn có thể tạo hàm trả lại tất cả các lớp học chú thích với @Document và cũng nhận được tất cả các bộ sưu tập từ MongoDB bắt đầu từ cars.<year>. Sau đó, bạn có thể phân tích tất cả các trường được chú thích bằng @Indexed và, kết quả là, gọi ensureIndex cho các trường này bằng cách sử dụng danh sách bộ sưu tập.

+0

@Dave: xem có thể bổ sung để trả lời –

1

tôi thực sự cần phải có khả năng xác định tên bộ sưu tập bằng tay vì:

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 

Đối với tuyên bố đầu tiên của bạn, bạn có thể thực thi một bộ sưu tập đĩa đơn sử dụng @Document siêu dữ liệu chú thích:

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

} 

Trường sưu tập của @Document sẽ đảm bảo rằng mọi phân lớp ô tô sẽ được đưa vào bộ sưu tập xe hơi, cộng với chỉ mục được tạo tự động với sự trợ giúp của chú thích @Indexed.

+0

Điều đó sẽ tốt, ngoại trừ, như bạn nói, nó không giúp tôi với điểm thứ hai = ( – Dave

+0

Tôi không hiểu điểm thứ hai của bạn. Vui lòng đưa ra một ví dụ –

+0

Điều chắc chắn. Bạn không chắc chắn về cách sử dụng trường hợp sử dụng rộng rãi này, nhưng đối với tôi, nó tạo ra rất nhiều ý nghĩa để duy trì các bộ sưu tập hoàn toàn riêng biệt cho từng khách hàng của tôi. Đối tượng thực tế mà tôi đang lưu trữ là một tweet (không phải là ô tô), và đối với mỗi khách hàng, tôi có thể thu thập hàng trăm nghìn tweet. Đối với mỗi tweet, tôi sẽ đính kèm các chú thích khác nhau cho từng khách hàng. Vì vậy, nếu họ là tất cả trong một bộ sưu tập, nó có thể nhận được rất lớn, và tôi phải thêm rất nhiều lĩnh vực phụ để theo dõi khách hàng nào quan tâm đến tweet và các chú thích trên đó. Một bộ sưu tập = lộn xộn, nhiều bộ sưu tập = sạch. – Dave

0

Bạn có thể tốt hơn khi dừng lại ở cấp DB và kiểm tra xem bộ sưu tập có chỉ mục bạn cần sử dụng getIndexes và gọi đảm bảo là một phần của ứng dụng của bạn khởi động.

Mẹo: Triển khai InitializingBean trên lớp cấu hình mongo cho ứng dụng của bạn và thực hiện phép thuật ở đó.

Không có lời rao giảng, IMHO Spring luôn giỏi về những thứ nhất định và những thứ khác ở những người khác. Tôi cố gắng tránh sự sưng lên khác với DI & quản lý TXN trong môi trường không phải XA.

0

Sau một tìm kiếm dài, tôi nghĩ rằng hiện tại không phải là posible bằng cách sử dụng chú thích, vì vậy tôi tạo ra một cách lập trình để quản lý kịch bản này.

tạo chỉ mục bình thường và chỉ mục tổng hợp

Trước tiên tôi đã xác định một đối tượng để ánh xạ cấu trúc chỉ mục.

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

Bộ sưu tập Json sẽ trông như thế này

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

Sau đó, chúng ta có thể tạo ra các bộ sưu tập và các chỉ số

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

Kết quả là danh sách chỉ số duy nhất có thể được sử dụng để tạo chỉ mục trường duy nhất

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

Chỉ số hợp chất hoặc chỉ số multifield là khôn lanh, Chúng ta cần tạo DBObjects để xác định chỉ số

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

Và kết quả có thể được sử dụng để tạo ra các chỉ số trong bộ sưu tập

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()); 
    } 
} 
Các vấn đề liên quan