mongodb存储数据_在MongoDB中存储分层数据

mongodb存储数据

继续使用MongoDB进行 NoSQL之旅,我想谈一谈一个经常出现的特定用例:存储分层文档关系。 MongoDB是很棒的文档数据存储,但是如果文档具有父子关系,该怎么办? 我们可以有效地存储和查询此类文档层次结构吗? 肯定的答案是,我们可以。 MongoDB对如何在MongoDB中存储树提出了一些建议。 那里描述的并且被广泛使用的一种解决方案是使用物化路径。

让我通过提供非常简单的示例来解释其工作原理。 如前几篇文章所述,我们将使用最近发布的Spring Data MongoDB项目的1.0版来构建Spring应用程序。 我们的POM文件包含非常基本的依赖关系,仅此而已。

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类的配置方法。 我越来越提倡使用这种样式,因为它提供了强大的类型化配置,并且大多数错误都可以在编译时发现,而无需再检查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() );}
}

很好,很清楚。 谢谢, 春天的家伙! 现在,所有样板文件已准备就绪。 让我们转到有趣的部分:文档。 我们的数据库将包含“文档”集合,其中存储了SimpleDocument类型的文档。 我们使用用于SimpleDocument POJO的Spring Data MongoDB批注对此进行描述。

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

让我在这里解释几件事。 首先,魔术属性路径 :这是构建和查询层次结构的关键。 路径包含所有文档父级的标识符,通常以某种分隔符(在我们的情况下为)分隔 (点) 。 以这种方式存储文档层次结构关系可以快速构建层次结构,进行搜索和导航。 其次,注意临时文档集合:此非持久集合由持久提供者构造,并包含所有后代文档(以防万一,还包含自己的后代)。 让我们通过查找find方法实现来实际观察它:

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

如您所见,要获得具有整个层次结构的单个文档,我们只需要运行两个查询(但是更优化的算法可以将其缩减为一个查询)。 这是一个示例层次结构,以及从MongoDB读取根文档的结果

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

而已。 简单一个强大的概念。 当然,在路径属性上添加索引将大大加快查询速度。 有很多改进和优化,但是基本思想现在应该很清楚。

参考:在Andriy Redko {devmind}博客上,由我们的JCG合作伙伴 Andrey Redko 在MongoDB中存储分层数据 。


翻译自: https://www.javacodegeeks.com/2012/01/storing-hierarchical-data-in-mongodb.html

mongodb存储数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序员如何快速成长为IT精英

很多程序员工作了很多年,仍然只学到了皮毛点的业务和技术,技术长时间没有提升,一直拖拖拉拉处于某个水平,没有接触到核心业务,也难于成为公司的中流砥柱和骨干。那么程序员该如何成长呢? 1.主动学习 时刻保持危机感,对知识保持好奇心,完善自己的职业规划和知识体系,掌…

hdu1521 指数型母函数

排列组合 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3438 Accepted Submission(s): 1439Problem Description有n种物品&#xff0c;并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品…

【Java从入门到天黑|06】高质量男性SpringBoot入门及原理(基础总结版,强烈建议收藏)

目录 SpringBoot简介 Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。 helloWorld

JavaFX实际应用程序:AISO HRC-Matic

“ Real-World JavaFX Apps”系列中的第三个应用程序是一种重型数据输入应用程序&#xff0c;由称为HRC-Matic的关系数据库支持。 它是由AISO在日内瓦开发的。 AISO是一家专门开发基于JavaFX的业务应用程序的公司。 他们还在研究我在本系列的第一个博客&#xff08; 欧洲广播联…

Feather包实现数据框快速读写,你值得拥有

什么是Feather&#xff1f; Feature是一种文件格式&#xff0c;支持R语言和Python的交互式存储&#xff0c;速度更快。目前支持R语言的data.frame和Python pandas 的DataFrame。 Feather收到了Apache arrow 项目的支持&#xff0c;Apache Arrow是Apache基金会下一个全新的开源项…

一文教你学会需求分析与管理

大家好,我是孙叫兽,本期给大家分享需求分析与管理,在项目开始或者需求整理时,这方面的知识显得尤为重要,常言道:良好的开始是成功的一半! 1.需求的定义 产品需求是在一定的时期,一定的场景中,无论是心理上还是生理上的,用户有着某种“需要”,这种“需要”用户自己不…

java 编写代码_Java 7:如何编写非常快速的Java代码

java 编写代码当我第一次写此博客时&#xff0c;我的目的是向您介绍ThreadLocalRandom类&#xff0c;它是Java 7中新增的用于生成随机数的类。 我在一系列微基准测试中分析了ThreadLocalRandom的性能&#xff0c;以了解其在单线程环境中的性能。 结果相对令人惊讶&#xff1a;尽…

POJ 1172 DFS

&#xff08;感谢wzc学长的幻灯片&#xff09; 单组数据 注意从必经点能到标记过的点则此点不是分裂点。 //By: Sirius_Ren #include <cstdio> #include <queue> #include <cstring> using namespace std; int tot1,first[51],cnt,v[101],nxt[101],n,vis[51…

文件夹或者文件比对工具 Beyond Compare

文件夹或者文件比对工具 Beyond Compare 之前有同事离职了。 没有工作交接。 同事的代码有一部分也没有提交版本库。 结果就是线上的代码和版本库中的文件数量和代码内容不一致。 这时就需要进行两方比对&#xff0c;查找不一致的地方。 如果人工…

Lucene查询(搜索)语法示例

本文是我们名为“ Apache Lucene基础知识 ”的学院课程的一部分。 在本课程中&#xff0c;您将了解Lucene。 您将了解为什么这样的库很重要&#xff0c;然后了解Lucene中搜索的工作方式。 此外&#xff0c;您将学习如何将Lucene Search集成到您自己的应用程序中&#xff0c;以…

远程桌面在自己电脑显示很小的解决办法

背景:最近在某银行办公,使用的是云桌面,疫情期间有一周是在加班办公,使用自己的电脑登录云桌面,然后电脑屏幕显示云桌面很小,看文档及代码十分难受。问问同事,这个问题终于得到了解决。 显示如下: 这个云桌面在我电脑就显示2/3宽度的大小,看代码太难受了,排除右上角向…

《JavaScript100例|01》之javaScript实现俄罗斯方块,唤起了女朋友儿时的回忆!

导读&#xff1a;小时候我们经常打游戏玩俄罗斯方块&#xff0c;用的是游戏机。 现在我们学会了敲代码&#xff0c;简单用JS实现一下这个游戏把。 目录 先看效果 操作说明 代码实现 完整代码 先看效果 操作说明 打开编译器&#xff0c;讲代码复制进去&#xff0c;在浏览…

JBOSS内存溢出处理

JBOSS内存溢出处理 前几天公司一个项目的服务器坏了&#xff0c;就换了一个备份服务器顶替一下&#xff0c;但是没有跑一会就宕机了&#xff0c;一直报java.lang.OutOfMemoryError。。。。一看到这里&#xff0c;就知道是内存溢出&#xff0c;但是JBoss的内存配置已经达到1024M…

linux命令之seq

seq命令简述 seq命令比较常用&#xff0c;在需要做循环的时候用于产生一个序列是再合适不过的工具了&#xff0c;常用方法也比较简单&#xff1a;Usage:seq [OPTION]... LASTseq [OPTION]... FIRST LASTseq [OPTION]... FIRST INCREMENT LASTPrint numbers from FIRST to LAST,…

史上最全高级Java教程总结版(强烈建议收藏)

本篇文章主要用于分享java相关的视频,课程等,涉及面比较广,建议先收藏再慢慢观看,信息量比较大。适合新手,老手各阶段Java程序员。 订阅本专栏 《高级java教程系列》 的福利! 目录 java知识体系列表 面试题库 java各知识点综合面试题

adf4351使用_ADF:将UI类别与动态表单一起使用

adf4351使用JDev 11g R2具有有趣的新功能“ UI类别”。 它使我们可以在视图对象定义级别上以声明方式对VO的属性进行分组。 例如&#xff0c;我的VEmployees视图对象的“ UI Categories”选项卡如下所示&#xff1a; 默认情况下&#xff0c;每个视图对象都有一个预定义的类别“…

使用JavaScript将小写金额转化为大写金额的两种常见方法

导读:在一些支付或者银行确认信息中经常需要将小写金额转换为大写金额,这里做一下归纳, 目录 效果图: 方法一:使用正则表达式 方法二:常规JavaScript实现 效果图: 前面小写,后面大写,这里使用vue测试,其它框架同理.小写是传值的字段money,大写直接调用函数dealBigMoney(money…

h5-列表

<header> <!-- a,div,header,span {-webkit-tap-highlight-color: rgba(255, 255, 255, 0); /*修改a、input和button点击时的蓝色外边框和灰色半透明背景*/ } --><div class"header"> <!-- .header {height: 44px;background: #ff8200;position…

什么是突变测试?

最近&#xff0c;我反复提到“ 突变测试 ”一词。 因为可以说这种方法能够以超出代码覆盖范围的方式检测测试安全网的空白&#xff0c;所以我花了一些时间来追赶这个话题&#xff0c;然后尝试一下。 这篇文章总结了我的发现&#xff0c;作为对该主题的快速介绍。 什么是变异测…