首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

Mongodb联合查询

2023-11-11 来源:花图问答

com.java.web;import java.util.List;import org.mongodb.framework.pojo.GeneralBean;import org.springframework.data.mongodb.core.mapping.DBRef;import org.springframework.data.mongodb.core.mapping.Document;@Documentpublic class Clazzes extends GeneralBean { /** * */ private static final long serialVersionUID = -1151165767494158740L; private String classRoom; private String classTeacher; @DBRef private List<Student> student; public String getClassRoom() { return this.classRoom; } public void setClassRoom(String classRoom) { this.classRoom = classRoom; } public String getClassTeacher() { return this.classTeacher; } public void setClassTeacher(String classTeacher) { this.classTeacher = classTeacher; } public List<Student> getStudent() { return this.student; } public void setStudent(List<Student> student) { this.student = student; } }

 

package com.java.web;import org.mongodb.framework.dao.GeneralDao;public interface ClazzesDao extends GeneralDao<Clazzes>{ }
package com.java.web;import org.mongodb.framework.dao.GeneralDaoImpl;import org.springframework.stereotype.Repository;@Repositorypublic class ClazzesDaoImpl extends GeneralDaoImpl<Clazzes> implements ClazzesDao{ @Override protected Class<Clazzes> getEntityClass() { // TODO Auto-generated method stub return Clazzes.class; }}
package com.java.web;import org.mongodb.framework.service.GeneralServiceImpl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.mongodb.core.query.Criteria;import org.springframework.data.mongodb.core.query.Query;import org.springframework.stereotype.Service;import com.java.manage.pojo.User;@Servicepublic class ClazzesService extends GeneralServiceImpl<Clazzes> { @Autowired private ClazzesDao clazzDao; /** * 根据用户id查询用户 * * @param id * @return * @throws Exception */ public Clazzes findClazzById(String id) throws Exception { Query query = new Query(); query.addCriteria(Criteria.where("_id").is(id)); // User user= this.userDao.findOneById(id); Clazzes clazz = this.clazzDao.findOneByQuery(query); if (clazz != null) return clazz; else return null; } }
package com.java.web;import org.mongodb.framework.pojo.GeneralBean;import org.springframework.data.mongodb.core.mapping.DBRef;import org.springframework.data.mongodb.core.mapping.Document;@Documentpublic class Student extends GeneralBean { /** * */ private static final long serialVersionUID = 5697238875408915428L; /** * */ private String name; private int age; private String enterYear; @DBRef private Clazzes clazzes; public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } public String getEnterYear() { return this.enterYear; } public void setEnterYear(String enterYear) { this.enterYear = enterYear; } public Clazzes getClazzes() { return this.clazzes; } public void setClazzes(Clazzes clazzes) { this.clazzes = clazzes; } }
package com.java.web;import org.mongodb.framework.dao.GeneralDao;public interface StudentDao extends GeneralDao<Student>{ }
package com.java.web;import org.mongodb.framework.dao.GeneralDaoImpl;import org.springframework.stereotype.Repository;@Repositorypublic class StudentDaoImpl extends GeneralDaoImpl<Student> implements StudentDao{ @Override protected Class<Student> getEntityClass() { // TODO Auto-generated method stub return Student.class; }}
package com.java.web;import org.mongodb.framework.dao.GeneralDaoImpl;import org.springframework.stereotype.Repository;@Repositorypublic class StudentDaoImpl extends GeneralDaoImpl<Student> implements StudentDao{ @Override protected Class<Student> getEntityClass() { // TODO Auto-generated method stub return Student.class; }}

上面贴的都是基本的代码,下面进行junit测试

package org.java.test;import java.util.ArrayList;import java.util.List;import org.junit.Before;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.transaction.annotation.Transactional;import com.java.web.Clazzes;import com.java.web.ClazzesService;import com.java.web.Student;import com.java.web.StudentDao;import com.java.web.StudentService;public class TestInertStudentClass { ApplicationContext ac=null; @Before public void befort(){ ac=new ClassPathXmlApplicationContext(new String[]{"application-config.xml","dispatcher-servlet.xml","dispatcher-shiro.xml"}); } /** * 添加学生并且绑定班级 * @throws Exception */ @Test public void InsertStudent() throws Exception { StudentDao studentdao=(StudentDao) ac.getBean("studentDaoImpl"); List<Student> studentList = new ArrayList<Student>(); ClazzesService clazzService = (ClazzesService)ac.getBean("clazzesService"); Clazzes clazz =clazzService.findClazzById("59658fd4d724ccce5ee5cc5b"); if(clazz!=null){ for(int i=0;i<10;i++){ Student student = new Student(); student.setAge(11); student.setClazzes(clazz); student.setEnterYear("2015"); student.setName("学生"+i); studentdao.insert(student); studentList.add(student); } clazz.setStudent(studentList); clazzService.save(clazz); } } /** * 初始化一个班级 * @throws Exception */ @Test public void InsertClazz() throws Exception{ ClazzesService clazzService = (ClazzesService)ac.getBean("clazzesService"); Clazzes c = new Clazzes(); c.setClassRoom("2014年1班"); c.setClassTeacher("Mrs zhang"); c.setStudent(new ArrayList()); clazzService.insert(c); } /** * 通过联合查询获取班级下的所有学生信息 * @throws Exception */ @Test public void getAllClazz() throws Exception{ ClazzesService clazzService = (ClazzesService)ac.getBean("clazzesService"); Clazzes c = clazzService.findClazzById("59658fd4d724ccce5ee5cc5b"); for(Student s :c.getStudent()){ System.out.println("联合查询学生姓名:"+s.getName()); } } /* * 通过学生的id获取学生的班级 */ @Test public void findAllStudent() throws Exception{ StudentService s = (StudentService)ac.getBean("studentService"); Student ss = s.findUserById("59658831d724a1cb751c3ef8"); //通过联合查询获取班级信息 System.out.println(ss.getClazzes().getClassRoom()); } /** * 删除学生的时候执行联合删除班级中的学生 * @throws Exception */ @Test public void deleteStudent() throws Exception{ StudentService s = (StudentService)ac.getBean("studentService"); ClazzesService clazzService = (ClazzesService)ac.getBean("clazzesService"); Student ss = s.findUserById("596591e1d7241f4590bddef5"); List<Student> list= ss.getClazzes().getStudent(); List<Student> listnew = new ArrayList<Student>(); for(Student stu:list){ if(!stu.getId().equals("596591e1d7241f4590bddef5")){ listnew.add(stu); } } Clazzes c = ss.getClazzes(); c.setStudent(listnew); clazzService.save(c); s.remove(ss); } }

 

Mongodb联合查询

标签:姓名   where   添加   删除   actor   tor   dispatch   repos   sse   

小编还为您整理了以下内容,可能对您也有帮助:

mongodb查询语句怎么合并查询结果

我可以提供一下思路:

用db.coll.find({},{"只显示一列数据,或者几列,越少越好,数据量大了就不好使了,因为后面要排序操作"})$natual:1 排序后,赋值到cursor,然后forEach() 里面用两个变量保存当前一条数据,和上一条数据,直到匹配条件成功,然后就可以返回前后和当前三条数据了。

另外一种办法,是基于上面的,定期 $natual:1出来的数据,追加一列有序数字或者字符,然后保存到另外一张新表,然后根据新表的ID ,查询新表匹配的数据,最后通过查出来的 有序的添加的那列KEY:value 再查询一次前后数据就出来了。

mongodb查询语句怎么合并查询结果

我可以提供一下思路:

用db.coll.find({},{"只显示一列数据,或者几列,越少越好,数据量大了就不好使了,因为后面要排序操作"})$natual:1 排序后,赋值到cursor,然后forEach() 里面用两个变量保存当前一条数据,和上一条数据,直到匹配条件成功,然后就可以返回前后和当前三条数据了。

另外一种办法,是基于上面的,定期 $natual:1出来的数据,追加一列有序数字或者字符,然后保存到另外一张新表,然后根据新表的ID ,查询新表匹配的数据,最后通过查出来的 有序的添加的那列KEY:value 再查询一次前后数据就出来了。

mongoDB应用篇-mongo聚合查询

如果我们在日常操作中,将部分数据存储在了MongoDB中,但是有需求要求我们将存储进去的文档数据,按照一定的条件进行查询过滤,得到想要的结果便于二次利用,那么我们就可以尝试使用MongoDB的聚合框架。

前面我们在学习文档查询的过程中,也介绍过一些查询的操作符,其中就有一部分是简单的查询聚合函数,例如 count 、 distinct 、 group 等,如果是简单的数据分析过滤,完全可以使用这些自带的聚合函数以及查询的操作符来完成文档的过滤查询操作

如果我们遇到了一些数据需要跨多个文本或者统计等操作,这个时候可能文档自身也较为复杂,查询操作符已经无法满足的时候,这个时候就需要使用MongoDB的聚合查询框架了。

使用聚合框架可以对集合中的文档进行变换和组合查询,基本上我们使用的时候,都是使用多个构件创建一个管道,用于对一连串的文档进行处理。这里的构件包括 筛选(filter) 、 投射(projecting) 、 分组(grouping) 、 排序(sorting) 、 (limiting) 以及 跳过(skipping)

MongoDB中需要使用聚合操作,一般使用 aggregate 函数来完成多个聚合之间的连接,aggregate() 方法的基本语法格式如下 :

现在假设我们有个集合articles,里面存储了文章的集合,大致如下:

但这时我们需要查询出来每一个作者写的文章数量,需要使用aggregate()计算 ,大致如下:

输出的结果为:

通过这个简单的案例我们就能输出想要的数据和属性名,大概分析一下刚刚的聚合查询语句, by_user字段进行分组,代表每个用户一条数据,而num_tutorial则是定义了数值类型计算的结果字段,$sum则是计算总和,相当于每个用户出现一次,都会+1,最终计算出来的总和通过num_tutorial字段进行输出

注:如果管道没有给出预期的结果,就需要进行调试操作,调试的时候,可以尝试先给一个管道操作符的条件,如果这个时候查询出来的结果是我们想要的,那么我们需要再去指定第二个管道操作符,依次操作,最后就会定位到出了问题的操作符

前面我们提到聚合查询会使用管道操作符,而每一个操作符就会接受一连串的文档,对这些文档进行一些类型转换,最后将转换以后的文档结果传递给下一个管道操作符来执行后续的操作,如果当前是最后一个管道操作符,那么则会显示给用户最后的文档数据。不同的管道操作符是可以按照顺序组合在一起使用,并且可以被重复执行多次,例如我们可以先使用$match然后再去、 match操作。

match管道操作符可以使用$gt、$lt、$in等操作符,进行过滤,不过需要注意的是不能在$match管道操作符中使用空间地理操作符。

在实际使用的过程中,尽可能的将 match操作符以后,再去投射或者执行分组操作的话,是可以利用索引的。

相比较一般的查询操作而言,使用管道操作,尤其是其中的投射操作更加强大。我们可以在查询文档结束以后利用 $project 操作符从文档中进行字段的提取,甚至于我们可以重命名字段,将部分字段映射成我们想要展示出去的字段,也可以对一部分字段进行一些有意义的处理。需要注意的是, $project 操作符可以传入两个参数,第一个是需要处理的属性名称,第二个则是0或者1,如果传入1,则代表当前的属性是需要显示出来的,如果是0或者不写,默认都是代表这个字段不需要显示出来

当然第二个参数也可以是一个表达式或者查询条件,满足当前表达式的数据也可以进行显示,接下来我们先准备一点数据:

接下来,我们来查询,条件是item字段为abc,quantity要大于5,并且我们只要item和price字段的结果,其他都排除掉:

可以看到结果为:

如果我们想要在原基础上改变某个字段的名称,例如将item改为item_code,可以利用$来完成,如下:

可以看到我们指定的名称item_code,而这个别名对应的字段item使用$作为前缀标记,代表将item字段映射为item_code,可以看到结果:

我们在投影的时候,除了可以将某个字段映射成其他字段以外,还可以针对某个字段进行一些简单的运算,最常见的就是 四则运算 ,即

加法( subtract )、乘法( divide )、求模( $mod ) ,

除此之外,还支持对字段进行 关系运算 (大小比较( " eq" )、大于( " gte" )、小于( " lte" )、不等于( " ifNull" ) )、

逻辑运算 (与( " or" )、非 ( " concat" )、截取( " toLower" ) )等

我们基于上面的需求,假设每一个价格是按照元为单位,现在要求输出W为单位,那么我们就需要对price进行除法运算,如下:

除此之外,我们也可以将计算完毕的price改名为priceW,即:

可以看到输出的结果为:

这时有一个需求,要求我们返回数据的同时还要yyyy-MM-dd格式的时间字符串,这个时候我们就需要对date字段进行时间函数和字符串混合处理了,如下:

这里需要注意的一点是, year:" substr函数将date字段的结果截取成字符串即可实现拼接

group的_id上,代表按照当前字段进行分组,例如,我们这里根据item进行分组:

在我们针对某个字段进行分组以后,我们可以针对每个分组进行一些操作符的使用,常见的例如: $sum 、 $avg 、 $min 、 $max 、 $first 、 $last 。

$avg 操作符用来返回每一个分组内的平均值

现在我们基于前面item的分组,我们想要算出来每个组内的平均价格是多少,如下:

$min 和 $max 操作符用于返回分组内最大的值和最小的值

除了平均值以外,我们现在将最贵的和最便宜的价格也要列出来,这个时候就可以使用这两个操作符了,如下:

$first 、 $last 则是可以获取当前分组中第一个或者最后一个的某个字段的结果,如下:

除此之外,我们还可以在分组的时候使用数组操作符,例如 $addToSet 可以判断,当前数组如果不包含某个条件,就添加到当前数组中, $push 则不管元素是否存在,都直接添加到数组中

注意:大部分管道操作符都是流式处理的,只要有新的文档进入,就可以对新的文档进行处理,但是 $group 代表必须收到全部文档以后才可以进行分组操作,才会将结果传递给后续的管道操作符,这就意味着,如果当前mongo是存在分片的,会先在每个分片上执行完毕以后,再把结果传递mongos进行统一的分组,剩下的管道操作符也不会在每个分片,而是mongos上执行了

如果我们现在遇到一些文档比较复杂,比如存在内嵌文档的存在,某个属性里面嵌套了一个数组,但是我们需要对内嵌的数组文档进行分析过滤等查询处理,这个时候就可以使用 $unwind 操作符将每一个文档中的嵌套数组文件拆分为一个个的文档便于进行后续的处理,例如我们需要将之前的set集合中关于请求的url以及ip的信息拆分出来,原始的格式如下:

我们可以使用命令进行拆分,如下:

结果为:

可以看到数据则是按照每一条信息的方式展示出来了,方便后续的计算以及输出,但是需要注意的一点是,这种方式,如果该文档中没有拆分的字段,或者是空数组,默认会直接排除,如果我们需要空数组等也输出计算出来,则可以指定 preserveNullAndEmptyArrays 参数,设置为true,则代表空数组或者不存在的文档也要拆分输出出来,即:

我们可以在管道查询的过程中,按照某个属性值或者多个属性的结果进行顺序排序,排序的方式与普通查询操作符中的sort操作符表现一致,与其他管道操作符一样,可以在任何阶段使用,但是,需要注意的一点是,建议在管道操作符第一阶段进行排序,因为此时的排序是可以触发索引的,如果在后续阶段进行排序,会消耗大量内存,并且耗时会很久,尤其是在有 $group 的情况下,如果放在 $group 操作符后面,会发现等到的时间很久,不仅仅是无法触发索引的问题,还和 $group 操作符是等待所有数据完毕才会触发的特性有关,因此需要格外注意。

结果如下,按照我们想要的结果进行了排序:

limit,只返回前两条数据,如下:

结果如下:

除了 skip,与之前的查询操作符作用也是一样的,用于在已经查询完毕的结果集中跳过前N条数据以后进行返回,我们将$skip加在刚刚的查询后面,如下:

这个时候可以看到返回的结果为空,什么结果都没有了,这是因为前一步管道已经了仅仅返回2条,而接着我们又跳过了前两条文档,因此返回的结果为空,我们将顺序调换一下,看看:

可以看到结果如下,与刚才的结果无异:

管道查询操作符有很多,除了上面学习的常用的部分,还有几十个,需要了解全部的可以参考官网:

https://docs.mongodb.com/manual/reference/command/aggregate/

除此之外,我们在学习的过程中了解到,部分查询操作符是可以触发索引的,例如 $project 、 $group 或者 $unwind 操作符,因此我们也建议 如果可以的话,尽量先使用这类管道操作符进行数据过滤,可以有效减少数据集大小和数量,而且管道如果不是直接从原先的集合中使用数据,那就无

法在筛选和排序中使用索引 ,例如我们先进行管道操作,再去将过滤好的数据进行 $sort 排序,会导致无法使用索引,效率大幅度下降,因此如果我们需要涉及到 $sort 操作的时候,如果可以尽可能在最开始就处理,这个时候可以使用索引,效率较高,然后再去进行管道查询筛选与分组等其他操作,可以有效的提高查询的效率。另外需要注意的一点是,在 MongoDB中会对每一个管道查询做,例如某一步管道查询操作导致内存占用超过20%,这个时候就会报错,无法继续使用管道 ,因为mongoDB本身每次最大是16Mb的数据量,为了尽可能避免或者减少这种问题,建议可以考虑尽可能的使用 $match 操作符过滤无用数据,减少数据总大小。同时也 因为管道查询是多步执行,例如 $group 则是等待所有数据完毕才会执行,因此可能会导致整体执行时间较久 ,也因为这样,才不建议在较高的实时查询需求上使用管道和查询,而是在 设计的时候尽可能直接使用查询操作符进行数据查询,触发更多的索引,更快的销量查询出来想要的结果。

MongoDB怎样添加和查询集合数据

MongoDB虽然也是一种数据库,不过它的数据是以键值对格式保存在集合里面的。今天咪咪我就来讲解一下MongoDB数据库怎样添加数据和查询数据。

首先,启动MongoDB数据库(不会的可参考我的其他指南,这里不多说),然后再连接MongoDB数据库。如图,使用 mongo命令就可以连接MongoDB数据库了。

如图,提示connecting to……,说明连接成功了。

接着使用use 数据库名来打开或者新建数据库。如果数据库存在,就会打开对应的数据库,如果数据库不存在,则会创建一个新的数据库并且打开数据库。

执行命令之后,就会出现这个提示,说明数据库打开了,并且现在开始使用这个数据库。

如图,通过db.集合名.insert()就可以往集合中插入数据,集合名可以自己定义,如果集合不存在,则创建新的集合,然后插入数据,如果集合存在,则打开集合并插入数据。

执行命令之后,提示“nInserted……”说明插入数据成功。

之前也说过,MongoDB数据库里面的数据是键值对形式,所以如果想要插入多条数据,可以这样写,也就是键值对之间用逗号隔开。

如果想要查询数据,则可以使用db.集合名.find()语句来查询。如果想要查询a集合里面的数据则用db.a.find()来查询。注意,find()表示查询全部的数据。

执行语句之后,集合中所有的数据都会显示出来。

如果想要查询出特定的数据,则可以在find里面添加键值对作为条件。比如我要查询name为mimi的数据则可以这样写。

执行语句之后,就可以查询到对应的数据了。集合中包含有name:mimi的数据只有一条,所以就显示一条。到此,MongoDB添加和查询集合数据的方法就分享完了。

显示全文