MongoDB教程-8

ObjectId

在之前的所有章节中,我们一直在使用MongoDB的Object Id。在本章中,我们将了解ObjectId的结构。

ObjectId是一个12字节的BSON类型,具有以下结构-- 1.

前4个字节代表自unix epoch以来的秒数
接下来的3个字节是机器标识符
接下来的2个字节是进程ID
最后3个字节是一个随机的计数器值
MongoDB使用ObjectIds作为每个文档的_id字段的默认值,它是在创建任何文档的时候产生的。ObjectId的复杂组合使得所有的_id字段都是唯一的。

创建新的ObjectId
要生成一个新的ObjectId,请使用下面的代码 --

>newObjectId = ObjectId()

上述语句返回了以下唯一生成的id−

ObjectId("5349b4ddd2781d08c09890f3")

代替MongoDB生成ObjectId,你也可以提供一个12字节的id --

>myObjectId = ObjectId("5349b4ddd2781d08c09890f4")

创建一个文档的时间戳
由于_id ObjectId默认存储4字节的时间戳,在大多数情况下,你不需要存储任何文档的创建时间。你可以使用getTimestamp方法获取一个文档的创建时间------。

>ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()

这将以ISO日期格式返回该文件的创建时间。

ISODate("2014-04-12T21:49:17Z")

将ObjectId转换为字符串
在某些情况下,你可能需要ObjectId的值为字符串格式。要将ObjectId转换为字符串,请使用下面的代码 -

>newObjectId.str

上面的代码将返回Guid的字符串格式------。

5349b4ddd2781d08c09890f3

Map Reduce

根据MongoDB文档,Map-reduce是一种数据处理范式,用于将大量的数据浓缩成有用的聚合结果。MongoDB使用mapReduce命令进行map-reduce操作。MapReduce通常用于处理大型数据集。

MapReduce命令
以下是基本的mapReduce命令的语法----。

>db.collection.mapReduce(function() {emit(key,value);},  //map functionfunction(key,values) {return reduceFunction}, {   //reduce functionout: collection,query: document,sort: document,limit: number}
)

map-reduce函数首先查询集合,然后对结果文件进行映射,发出键值对,再根据有多个值的键进行还原。

在上面的语法中--

map是一个javascript函数,它将一个值与一个键进行映射,并发射出一个键值对

reduce是一个javascript函数,用于减少或分组所有具有相同键的文件。

out指定map-reduce查询结果的位置

query指定选择文档的可选选择标准

sort指定了可选的排序标准

limit指定了可选的返回的最大文件数。

使用MapReduce
考虑下面这个存储用户帖子的文档结构。该文档存储了用户的用户名和帖子的状态。

{"post_text": "tutorialspoint is an awesome website for tutorials","user_name": "mark","status":"active"
}

现在,我们将在我们的帖子集合上使用mapReduce函数来选择所有的活动帖子,根据用户名对它们进行分组,然后使用以下代码计算每个用户的帖子数量------。

>db.posts.mapReduce( function() { emit(this.user_id,1); }, function(key, values) {return Array.sum(values)}, {  query:{status:"active"},  out:"post_total" }
)

上述mapReduce查询输出的结果如下 -

{"result" : "post_total","timeMillis" : 9,"counts" : {"input" : 4,"emit" : 4,"reduce" : 2,"output" : 2},"ok" : 1,
}

结果显示,共有4个文档与查询相匹配(status: "active"),map函数发出了4个有键值对的文档,最后reduce函数将有相同键值的映射文档归为2个。

要看这个mapReduce查询的结果,请使用查找操作符--

>db.posts.mapReduce( function() { emit(this.user_id,1); }, function(key, values) {return Array.sum(values)}, {  query:{status:"active"},  out:"post_total" }).find()

上述查询给出了以下结果,表明用户tom和mark都有两个处于活动状态的帖子 -

{ "_id" : "tom", "value" : 2 }
{ "_id" : "mark", "value" : 2 }

以类似的方式,MapReduce查询可用于构建大型复杂的聚合查询。使用自定义的Javascript函数可以利用MapReduce,它是非常灵活和强大的。

文本搜索

从2.4版本开始,MongoDB开始支持文本索引来搜索字符串内容内部。文本搜索使用词干技术,通过丢弃像a、an、the等词干的停顿词来寻找字符串字段中的指定词。目前,MongoDB支持大约15种语言。

启用文本搜索
最初,文本搜索是一个实验性的功能,但从2.6版本开始,该配置被默认启用。

创建文本索引
考虑在post集合下的以下文件,其中包含帖子文本及其标签------。

> db.posts.insert({"post_text": "enjoy the mongodb articles on tutorialspoint","tags": ["mongodb", "tutorialspoint"]
}
{"post_text" : "writing tutorials on mongodb","tags" : [ "mongodb", "tutorial" ]
})
WriteResult({ "nInserted" : 1 })

我们将在post_text字段上创建一个文本索引,这样我们就可以在我们的帖子的文本中进行搜索了。

>db.posts.createIndex({post_text:"text"})
{"createdCollectionAutomatically" : true,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}

使用文本索引
现在我们已经在post_text字段上创建了文本索引,我们将搜索所有文本中含有tutorialspoint一词的帖子。

> db.posts.find({$text:{$search:"tutorialspoint"}}).pretty()
{"_id" : ObjectId("5dd7ce28f1dd4583e7103fe0"),"post_text" : "enjoy the mongodb articles on tutorialspoint","tags" : ["mongodb","tutorialspoint"]
}

上述命令返回的结果是,在其帖子文本中有tutorialspoint一词的文件 -

{ "_id" : ObjectId("53493d14d852429c10000002"), "post_text" : "enjoy the mongodb articles on tutorialspoint", "tags" : [ "mongodb", "tutorialspoint" ]
}

删除文本索引
要删除一个现有的文本索引,首先使用以下查询找到索引的名称

>db.posts.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "mydb.posts"},{"v" : 2,"key" : {"fts" : "text","ftsx" : 1},"name" : "post_text_text","ns" : "mydb.posts","weights" : {"post_text" : 1},"default_language" : "english","language_override" : "language","textIndexVersion" : 3}
]
>

从上面的查询中得到你的索引名称后,运行以下命令。这里,post_text_text是索引的名称。

>db.posts.dropIndex("post_text_text")
{ "nIndexesWas" : 2, "ok" : 1 }

正则

正则表达式在所有语言中都经常被用来搜索任何字符串中的模式或单词。MongoDB也提供了正则表达式的功能,使用$regex操作符进行字符串模式匹配。MongoDB使用PCRE(Perl Compatible Regular Expression)作为正则表达式语言。

与文本搜索不同,我们不需要做任何配置或命令来使用正则表达式。

假设我们在一个名为post的数据库中插入了一个文件,如下图所示

> db.posts.insert(
{"post_text": "enjoy the mongodb articles on tutorialspoint","tags": ["mongodb","tutorialspoint"]
}
WriteResult({ "nInserted" : 1 })

使用regex表达式
下面的regex查询可以搜索到所有含有字符串tutorialspoint的帖子 -

> db.posts.find({post_text:{$regex:"tutorialspoint"}}).pretty()
{"_id" : ObjectId("5dd7ce28f1dd4583e7103fe0"),"post_text" : "enjoy the mongodb articles on tutorialspoint","tags" : ["mongodb","tutorialspoint"]
}
{"_id" : ObjectId("5dd7d111f1dd4583e7103fe2"),"post_text" : "enjoy the mongodb articles on tutorialspoint","tags" : ["mongodb","tutorialspoint"]
}
>

同样的查询也可以写成--

>db.posts.find({post_text:/tutorialspoint/})

使用不区分大小写的regex表达式
为了使搜索不区分大小写,我们使用$options参数,其值为$i。下面的命令将寻找有tutorialspoint这个词的字符串,不管是小写还是大写------。

>db.posts.find({post_text:{$regex:"tutorialspoint",$options:"$i"}})

该查询返回的结果之一是以下文件,该文件在不同情况下包含tutorialspoint一词--

{"_id" : ObjectId("53493d37d852429c10000004"),"post_text" : "hey! this is my post on TutorialsPoint", "tags" : [ "tutorialspoint" ]
} 

对数组元素使用regex
我们也可以在数组领域使用regex的概念。当我们实现标签的功能时,这一点尤其重要。因此,如果你想搜索所有标签以tutorial(或tutorial或tutorialpoint或tutorialphp)开头的帖子,你可以使用以下代码

>db.posts.find({tags:{$regex:"tutorial"}})

优化正则表达式查询
如果文档字段是有索引的,查询将利用索引值来匹配正则表达式。与正则表达式扫描整个集合相比,这使得搜索的速度非常快。

如果正则表达式是一个前缀表达式,那么所有的匹配都要以某个字符串字符开始。例如,如果正则表达式是^tut,那么查询就必须只搜索以tut开头的字符串。

GridFS

GridFS是MongoDB的规范,用于存储和检索大型文件,如图像、音频文件、视频文件等。它是一种存储文件的文件系统,但其数据被存储在MongoDB集合中。GridFS有能力存储文件,甚至超过其文件大小的限制(16MB)。

GridFS将文件分成几块,并将每块数据存储在一个单独的文档中,每块最大尺寸为255k。

GridFS默认使用两个集合fs.files和fs.chunks来存储文件的元数据和分块。每个块由其唯一的_id ObjectId字段来识别。fs.files作为一个父文件。fs.chunks文档中的files_id字段将块链接到它的父文档。

以下是fs.files集合的一个样本文件----。

{"filename": "test.txt","chunkSize": NumberInt(261120),"uploadDate": ISODate("2014-04-13T11:32:33.557Z"),"md5": "7b762939321e146569b07f72c62cca4f","length": NumberInt(646)
}

该文件指定了文件名、块状大小、上传日期和长度。

以下是fs.chunks文件的一个样本 -

{"files_id": ObjectId("534a75d19f54bfec8a2fe44b"),"n": NumberInt(0),"data": "Mongo Binary Data"
}

将文件添加到GridFS
现在,我们将使用GridFS的put命令来存储一个MP3文件。为此,我们将使用Mongofiles.exe工具,它存在于MongoDB安装文件夹的bin文件夹中。

打开你的命令提示符,导航到MongoDB安装文件夹的bin文件夹中的mongofiles.exe,然后输入以下代码

>mongofiles.exe -d gridfs put song.mp3

在这里,gridfs是数据库的名称,文件将被存储在其中。如果该数据库不存在,MongoDB将自动创建一个新的文件。Song.mp3是上传文件的名称。要在数据库中看到该文件的文档,你可以使用查找查询----。

>db.fs.files.find()

上述命令返回了以下文件 -

{_id: ObjectId('534a811bf8b4aa4d33fdf94d'), filename: "song.mp3", chunkSize: 261120, uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41",length: 10401959 
}

我们还可以使用前面查询中返回的文档id,使用以下代码查看fs.chunks集合中与存储文件相关的所有块

>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})

在我的例子中,查询返回了40个文件,这意味着整个MP3文件被分成了40块数据。

封顶集合是固定大小的循环集合,它遵循插入顺序,以支持创建、读取和删除操作的高性能。所谓循环,是指当分配给集合的固定大小用完时,它将开始删除集合中最古老的文档,而不提供任何明确的命令。

如果更新导致文档大小增加,封顶的集合就会限制对文档的更新。由于有上限的集合是按照磁盘存储的顺序来存储文档的,它可以确保文档的大小不会增加磁盘上分配的大小。封顶集合最适合于存储日志信息、缓存数据或任何其他高容量数据。

创建封顶集合
为了创建一个有上限的集合,我们使用普通的createCollection命令,但是将capped选项设为true,并指定集合的最大尺寸(字节)。

>db.createCollection("cappedLogCollection",{capped:true,size:10000})

除了集合大小,我们还可以使用max参数−限制集合中的文档数量

>db.createCollection("cappedLogCollection",{capped:true,size:10000,max:1000})

如果要检查集合是否有上限,请使用以下isCapped命令−

>db.cappedLogCollection.isCapped()

如果有一个现有的集合,你打算将其转换为封顶,你可以用下面的代码来做 --

>db.runCommand({"convertToCapped":"posts",size:10000})

这段代码将把我们现有的集合帖子转换为一个有上限的集合。

查询封顶的集合
默认情况下,在一个封顶的集合上的查找查询将以插入的顺序显示结果。但是如果你想以相反的顺序检索文件,请使用排序命令,如下代码所示

>db.cappedLogCollection.find().sort({$natural:-1})

关于有上限的集合,还有几个重要的点值得了解

我们不能从一个封顶的集合中删除文档。

在一个封顶的集合中没有默认的索引,甚至在_id字段上也没有。

当插入一个新的文档时,MongoDB不需要在磁盘上寻找一个位置来容纳新的文档。它可以盲目地在集合的尾部插入新的文档。这使得在有上限的集合中的插入操作非常快。

同样地,在读取文档时,MongoDB会按照磁盘上的相同顺序返回文档。这使得读取操作变得非常快。

自增

MongoDB并不像SQL数据库那样有开箱即用的自动递增功能。默认情况下,它使用12字节的ObjectId作为_id字段的主键来唯一地识别文档。然而,在某些情况下,我们可能希望_id字段有一些自动递增的值,而不是ObjectId。

由于这不是MongoDB的默认功能,我们将通过使用MongoDB文档中建议的计数器集合以编程方式实现这一功能。

使用计数器集合
考虑下面这个产品文档。我们希望_id字段是一个自动递增的整数序列,从1,2,3,4开始一直到n。

{"_id":1,"product_name": "Apple iPhone","category": "mobiles"
}

为此,创建一个计数器集合,它将跟踪所有序列字段的最后一个序列值。

>db.createCollection("counters")

现在,我们将在计数器集合中插入以下文件,以productid为其键 -

> db.counters.insert({"_id":"productid","sequence_value": 0
})
WriteResult({ "nInserted" : 1 })
>

字段sequence_value记录了该序列的最后一个值。

>db.counters.insert({_id:"productid",sequence_value:0})

创建Javascript函数
现在,我们将创建一个函数getNextSequenceValue,它将把序列名称作为其输入,将序列号增加1并返回更新的序列号。在我们的例子中,序列名称是 productid。

>function getNextSequenceValue(sequenceName){var sequenceDocument = db.counters.findAndModify({query:{_id: sequenceName },update: {$inc:{sequence_value:1}},new:true});return sequenceDocument.sequence_value;
}

使用Javascript函数
我们现在将在创建一个新文档时使用函数getNextSequenceValue,并将返回的序列值指定为文档的_id字段。

使用下面的代码插入两个样本文件--

>db.products.insert({"_id":getNextSequenceValue("productid"),"product_name":"Apple iPhone","category":"mobiles"
})
>db.products.insert({"_id":getNextSequenceValue("productid"),"product_name":"Samsung S3","category":"mobiles"
})

正如你所看到的,我们已经使用getNextSequenceValue函数来设置_id字段的值。

为了验证该功能,让我们使用find命令来获取文件 --

>db.products.find()

上述查询返回以下具有自动递增的_id字段的文件 -

{ "_id" : 1, "product_name" : "Apple iPhone", "category" : "mobiles"}
{ "_id" : 2, "product_name" : "Samsung S3", "category" : "mobiles" }

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

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

相关文章

maven 模块打包时包含依赖和打包可执行的jar

maven 模块打包 1)maven 模块打包jar文件时,指定包含依赖(with-dependencies); 2)maven 模块打包jar文件时,指定入口MainClass、打包生成可执行的jar; vi qftools/common/src/main…

与“云”共舞,联想凌拓的新科技与新突破

伴随着数字经济的高速发展,IT信息技术在数字中国建设中起到的驱动和支撑作用也愈发凸显。特别是2023年人工智能和ChatGPT在全球的持续火爆,更是为整个IT产业注入了澎湃动力。那么面对日新月异的IT信息技术,再结合疫情之后截然不同的经济环境和…

【Odoo16前端源码分析】xml模板的加载

1 模板内容的来源 情况A,组件类的template属性,比如ActionContainer.template /* odoo/addons/web/static/src/webclient/actions/action_container.js */export class ActionContainer extends Component {setup() {..} } .. ActionContainer.templat…

效率提升丨大学必看校园安全实用技巧

在当今社会,教育是培养人才、传承文明的重要场所。然而,教学楼作为学生、教师和员工活动的核心区域,也存在着潜在的安全隐患,其中最为突出的风险之一是火灾。火灾不仅危及生命财产,还可能给整个学校带来不可估量的损失…

vue3中使用原始标签制作一个拖拽和点击上传组件上传成功后展示

在Vue3中&#xff0c;可以使用<input type"file">标签来实现上传文件的功能&#xff0c;同时可以通过<div>标签来实现拖拽上传的功能。 首先&#xff0c;在template中定义一个包含<input>和<div>标签的组件&#xff1a; <template>&…

关于Android studio中的自动化测试脚本UiAutomator框架以及UiAutomatorViewer工具的使用——项目案例

加入依赖 implementation androidx.test.uiautomator:uiautomator:2.2.0创建CalcActivity页 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"

【C++】模板学习(二)

模板学习 非类型模板参数模板特化函数模板特化类模板特化全特化偏特化 模板分离编译模板总结 非类型模板参数 模板参数除了类型形参&#xff0c;还可以是非类型的形参。 非类型形参要求用一个常量作为类(函数)模板的一个参数。这个参数必须是整形家族的。浮点数&#xff0c;字…

Rust的入门篇(中)

Rust的入门篇(中) 这是接上面一篇rust入门篇(上)文章 22. 包管理一 mod nation {pub mod government {pub fn govern() {}}mod congress {pub fn legislate() {}}mod court {fn judicial() {super::congress::legislate();}} }fn main() {nation::government::govern(); }23.…

pytorch学习——正则化技术——丢弃法(dropout)

一、概念介绍 在多层感知机&#xff08;MLP&#xff09;中&#xff0c;丢弃法&#xff08;Dropout&#xff09;是一种常用的正则化技术&#xff0c;旨在防止过拟合。&#xff08;效果一般比前面的权重衰退好&#xff09; 在丢弃法中&#xff0c;随机选择一部分神经元并将其输出…

Vue 常用指令 v-model 双向数据绑定

之前的指令&#xff0c;无论使用哪一种&#xff0c;都是在代码当中定义的内容。在web开发当中经常要去获取用户的输入&#xff0c;v-model可以十分方便的将表单的值和实例当中的数据关联起来。 这样就可以十分便捷的获取和设置表单元素的值了。&#xff08;注意是表单元素&…

SpringBoot第29讲:SpringBoot集成MySQL - MyBatis-Plus代码自动生成

SpringBoot第29讲&#xff1a;SpringBoot集成MySQL - MyBatis-Plus代码自动生成 本文是SpringBoot第29讲&#xff0c;主要介绍 MyBatis-Plus代码自动生成&#xff0c;以及产生此类代码生成工具的背景和此类工具的基本实现原理。 文章目录 SpringBoot第29讲&#xff1a;SpringBo…

【Linux】Centos7 的 Systemctl 与 创建系统服务 (shell脚本)

Systemctl systemctl 命令 # 启动 systemctl start NAME.service # 停止 systemctl stop NAME.service # 重启 systemctl restart NAME.service # 查看状态 systemctl status NAME.service # 查看所有激活系统服务 systemctl list-units -t service # 查看所有系统服务 syste…

PHP高级检索功能的实现以及动态拼接sql

我们学习了解了这么多关于PHP的知识&#xff0c;不知道你们对PHP高级检索功能的实现以及动态拼接sql是否已经完全掌握了呢&#xff0c;如果没有&#xff0c;那就跟随本篇文章一起继续学习吧! PHP高级检索功能的实现以及动态拼接sql。完成的功能有&#xff1a;可以单独根据一个…

华为云hcip核心知识笔记(数据库服务规划)

华为云hcip核心知识笔记&#xff08;数据库服务规划&#xff09; 1.云数据接库优势 1.1云数据库优点有&#xff1a; 易用性强&#xff1a;能欧快速部署和运行 高扩展&#xff1a;开放式架构和云计算存储分离 低成本&#xff1a;按需使用&#xff0c;成本更加低廉 2.云数据库r…

微软开测“Moment4”启动包:Win11 23H2要来了

近日&#xff0c; 有用户在Win11最新的7月累积更新中发现&#xff0c;更新文件中已经开始出现了对“Moment4”的引用。 具体来说&#xff0c;在7月累积更新中&#xff0c;微软加入了“Microsoft-Windows-UpdateTargeting-ClientOS-SV2Moment4-EKB”“Microsoft-Windows-23H2Ena…

2023年【零声教育】13代C/C++Linux服务器开发高级架构师课程体系分析

对于零声教育的C/CLinux服务器高级架构师的课程到2022目前已经迭代到13代了&#xff0c;像之前小编也总结过&#xff0c;但是课程每期都有做一定的更新&#xff0c;也是为了更好的完善课程跟上目前互联网大厂的岗位技术需求&#xff0c;之前课程里面也包含了一些小的分支&#…

使用Vue.js和Rust构建高性能的物联网应用

物联网(IoT)应用是现代技术的重要组成部分&#xff0c;它们可以在各种场景中&#xff08;例如智能家居&#xff0c;工业自动化等&#xff09;提供无缝的自动化解决方案。在这篇文章中&#xff0c;我们将探讨如何使用Vue.js和Rust构建高性能的物联网应用。 1. 为什么选择Vue.js…

音频客观感知MOS对比,对ViSQOL、PESQ、MosNet(神经网络MOS分)和polqa一致性对比和可信度雁阵

原创&#xff1a;转载需附链接&#xff1a; 音频客观感知MOS对比&#xff0c;对ViSQOL、PESQ、MosNet&#xff08;神经网络MOS分&#xff09;和polqa一致性对比和可信度雁阵_machine-lv的博客-CSDN博客谢谢&#xff01; 本文章以标准polqa的mos分为可信前提&#xff0c;验证vis…

MPAndroidChart学习及问题处理

1.添加依赖 项目目录->app->build.gradle dependencies {implementation com.github.PhilJay:MPAndroidChart:v3.0.3 }项目目录->app->setting.gradle dependencyResolutionManagement {repositories {maven { url https://jitpack.io }} }高版本的gradle添加依…