在MongoDB中存储分层数据
讓我通過提供非常簡單的示例來解釋其工作原理。 如前幾篇文章所述,我們將使用最近發(fā)布的Spring Data MongoDB項(xiàng)目的1.0版來構(gòu)建Spring應(yīng)用程序。 我們的POM文件包含非?;镜囊蕾囆?#xff0c;僅此而已。
4.0.0mongodbcom.example.spring0.0.1-SNAPSHOTjarUTF-83.0.7.RELEASEorg.springframework.dataspring-data-mongodb1.0.0.RELEASEorg.springframeworkspring-beansorg.springframeworkspring-expressioncglibcglib-nodep2.2log4jlog4j1.2.16org.mongodbmongo-java-driver2.7.2org.springframeworkspring-core${spring.version}org.springframeworkspring-context${spring.version}org.springframeworkspring-context-support${spring.version}org.apache.maven.pluginsmaven-compiler-plugin2.3.21.61.6為了正確配置Spring上下文,我將使用利用Java類的配置方法。 我越來越提倡使用這種樣式,因?yàn)樗峁┝藦?qiáng)大的類型化配置,并且大多數(shù)錯(cuò)誤都可以在編譯時(shí)發(fā)現(xiàn),而無需再檢查XML文件。 這里看起來像:
package com.example.mongodb.hierarchical;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoFactoryBean; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory;@Configuration public class AppConfig {@Beanpublic MongoFactoryBean mongo() {final MongoFactoryBean factory = new MongoFactoryBean();factory.setHost( "localhost" );return factory;}@Beanpublic SimpleMongoDbFactory mongoDbFactory() throws Exception{return new SimpleMongoDbFactory( mongo().getObject(), "hierarchical" );}@Beanpublic MongoTemplate mongoTemplate() throws Exception {return new MongoTemplate( mongoDbFactory() );}@Beanpublic IDocumentHierarchyService documentHierarchyService() throws Exception {return new DocumentHierarchyService( mongoTemplate() );} }很好,很清楚。 謝謝, 春天的家伙! 現(xiàn)在,所有樣板文件已準(zhǔn)備就緒。 讓我們轉(zhuǎn)到有趣的部分:文檔。 我們的數(shù)據(jù)庫將包含“文檔”集合,其中存儲(chǔ)了SimpleDocument類型的文檔。 我們使用針對(duì)SimpleDocument POJO的Spring Data MongoDB批注對(duì)此進(jìn)行描述。
package com.example.mongodb.hierarchical;import java.util.Collection; import java.util.HashSet;import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field;@Document( collection = "documents" ) public class SimpleDocument {public static final String PATH_SEPARATOR = ".";@Id private String id;@Field private String name;@Field private String path;// We won't store this collection as part of document but will build it on demand@Transient private Collection< SimpleDocument > documents = new HashSet< SimpleDocument >();public SimpleDocument() {}public SimpleDocument( final String id, final String name ) {this.id = id;this.name = name;this.path = id;}public SimpleDocument( final String id, final String name, final SimpleDocument parent ) {this( id, name );this.path = parent.getPath() + PATH_SEPARATOR + id;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public Collection< SimpleDocument > getDocuments() {return documents;} }讓我在這里解釋幾件事。 首先,魔術(shù)屬性路徑 :這是構(gòu)造和查詢層次結(jié)構(gòu)的關(guān)鍵。 路徑包含所有文檔父級(jí)的標(biāo)識(shí)符,通常以某種分隔符(在我們的情況下為)分隔。 (點(diǎn)) 。 以這種方式存儲(chǔ)文檔層次結(jié)構(gòu)關(guān)系可以快速構(gòu)建層次結(jié)構(gòu),進(jìn)行搜索和導(dǎo)航。 其次,注意臨時(shí)文檔集合:此非持久集合是由持久提供程序構(gòu)造的,并且包含所有后代文檔(以防萬一,還包含自己的后代)。 讓我們通過查找find方法實(shí)現(xiàn)來實(shí)際觀察它:
package com.example.mongodb.hierarchical;import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map;import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query;public class DocumentHierarchyService {private MongoOperations template;public DocumentHierarchyService( final MongoOperations template ) {this.template = template;}@Overridepublic SimpleDocument find( final String id ) {final SimpleDocument document = template.findOne(Query.query( new Criteria( "id" ).is( id ) ),SimpleDocument.class);if( document == null ) {return document;}return build(document,template.find(Query.query( new Criteria( "path" ).regex( "^" + id + "[.]" ) ),SimpleDocument.class));}private SimpleDocument build( final SimpleDocument root, final Collection< SimpleDocument > documents ) {final Map< String, SimpleDocument > map = new HashMap< String, SimpleDocument >();for( final SimpleDocument document: documents ) {map.put( document.getPath(), document );}for( final SimpleDocument document: documents ) {map.put( document.getPath(), document );final String path = document.getPath().substring( 0, document.getPath().lastIndexOf( SimpleDocument.PATH_SEPARATOR ) );if( path.equals( root.getPath() ) ) {root.getDocuments().add( document );} else {final SimpleDocument parent = map.get( path );if( parent != null ) {parent.getDocuments().add( document );}}}return root;} }如您所見,要獲得具有整個(gè)層次結(jié)構(gòu)的單個(gè)文檔,我們只需要運(yùn)行兩個(gè)查詢(但更優(yōu)化的算法可以將其縮減為一個(gè)查詢)。 這是一個(gè)示例層次結(jié)構(gòu),以及從MongoDB讀取根文檔的結(jié)果
template.dropCollection( SimpleDocument.class );final SimpleDocument parent = new SimpleDocument( "1", "Parent 1" ); final SimpleDocument child1 = new SimpleDocument( "2", "Child 1.1", parent ); final SimpleDocument child11 = new SimpleDocument( "3", "Child 1.1.1", child1 ); final SimpleDocument child12 = new SimpleDocument( "4", "Child 1.1.2", child1 ); final SimpleDocument child121 = new SimpleDocument( "5", "Child 1.1.2.1", child12 ); final SimpleDocument child13 = new SimpleDocument( "6", "Child 1.1.3", child1 ); final SimpleDocument child2 = new SimpleDocument( "7", "Child 1.2", parent );template.insertAll( Arrays.asList( parent, child1, child11, child12, child121, child13, child2 ) );...final ApplicationContext context = new AnnotationConfigApplicationContext( AppConfig.class ); final IDocumentHierarchyService service = context.getBean( IDocumentHierarchyService.class );final SimpleDocument document = service.find( "1" ); // Printing document show following hierarchy: // // Parent 1 // |-- Child 1.1 // |-- Child 1.1.1 // |-- Child 1.1.3 // |-- Child 1.1.2 // |-- Child 1.1.2.1 // |-- Child 1.2而已。 簡單一個(gè)強(qiáng)大的概念。 當(dāng)然,在路徑屬性上添加索引將大大加快查詢速度。 有很多改進(jìn)和優(yōu)化,但是基本思想現(xiàn)在應(yīng)該很清楚。
參考: Andriy Redko {devmind}博客上的JCG合作伙伴 Andrey Redko 在MongoDB中存儲(chǔ)分層數(shù)據(jù) 。
翻譯自: https://www.javacodegeeks.com/2012/01/storing-hierarchical-data-in-mongodb.html
總結(jié)
以上是生活随笔為你收集整理的在MongoDB中存储分层数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何暴增弹跳力(提高弹跳力和爆发力的训练
- 下一篇: 电脑ps快捷键截图(PS截图的快捷键)