Mongodb 语句使用

以下集合全部是用user,task集合,Mongodb的文档相当于MYSQL的行记录。有一些关键字加上了双引号是因为我在python中使用的大多数的$开头的关键字在mongodb查询里是不需要添加双引号的。

1,增

MongoDB 使用 insert() 或 save() 方法向集合中插入文档。
3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。           
1,save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 
	或 db.collection.replaceOne() 来代替。
2,insert(): 若插入的数据主键已经存在,则会抛出主键重复异常

db.user.save({key:value})
db.user.insert({key:value})
db.user.insertOne({key:value})
db.user.insertMany([{key:value},{key:val}])

2,查($xx:操作符)

MongoDB 使用 find(),findOne()方法向集合中查找文档,findOne()方法只会返回一个文档。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
	db.user.find({},{key:0,key:1}).pretty()  #find(筛选条件,某列是否查询(0-不查询,1-查询),默认全部查询)
	
· 等于-走索引:		db.user.find({key:value}).pretty() 
· 小于-尝试使用索引:		db.user.find({key:{$lt:value}}).pretty()
	对于数值型索引,$lt 可以使用索引来优化查询,因为索引中存储的值都是有序的,可以快速定位到小于该值的文档。
	对于字符串型索引,$lt 也是可以使用索引来优化查询,因为字符串也是有序的。
	对于数组字段索引,$lt 查询会返回结果,但是不能使用索引加速查询。
	总之,$lt 查询可以使用索引来优化查询,对于数值型和字符串型索引是可以的,对于数组字段索引,虽然可以查询出结果,但是无法使用
	索引加速查询。
· 小于等于-索引与小于一样:	db.user.find({key:{$lte:value}}).pretty()
· 大于-索引与小于一样:		db.user.find({key:{$gt:value}}).pretty()
· 大于等于-索引与小于一样:	db.user.find({key:{$gte:value}}).pretty()
· 不等于-会尝试使用索引来优化查询:
	$ne 查询会对索引产生负面影响,因为它需要返回所有不等于该值的文档,而不仅仅是索引中有的文档。这意味着在查询中使用 $ne 
	可能会导致全集合扫描,这样会导致性能问题。	
	在使用 $ne 查询时,应该尽量避免使用索引字段,而应该使用其他字段来进行查询,这样可以避免全集合扫描。
	例:
		db.user.find({key:{$ne:value}}).pretty()
· 模糊查询(正则)-不走索引:	db.user.find({key:{$regex:/value/}}).pretty()
· 查询是否存在某个字段--不走索引(1或者true都行:db.user.find({key:{$exists:1}}).pretty()
· in-数组大小过大,这可能会导致索引失效:		db.user.find({key:{$in:[v1,v2]}}).pretty()
· not in-数组大小过大,这可能会导致索引失效 :	db.user.find({key:{$nin:[v1,v2]}}).pretty()


· And-需要创建复合索引:db.collection.find( { $and: [ { field1: value1 }, { field2: value2 }, { field3: value3 } ] } )
	创建复合索引:db.collection.createIndex( { field1: 1, field2: 1, field3: 1 } )
	遵循类似于 MySQL 的最左前缀原则:
	
		在使用复合索引时,MongoDB 会尝试使用索引的第一个字段来进行匹配,如果匹配成功,则使用第二个字段进行匹配,以此类推。
		如果在某一步匹配失败,则整个查询将会失败。
	
		这也是为什么需要按照索引字段的顺序来排列条件,因为MongoDB会按照索引字段的顺序来进行匹配。
	
		在使用复合索引时,通常建议将经常使用的字段放在索引的最左边,这样可以更好的利用索引来加速查询。

· OR-不走索引:  	 db.user.find({$or:[{key1:value1},{key2: value2}]}).pretty()
· Not-不走索引: 	 db.user.find({key:{$not:{$eq:value}}}).pretty() 
· NotOr-尝试使用索引:	 db.user.find({$nor:[{name:'小博'},{name:'测试小博'}]}) 比如查询name不为“小博”或者“测试小博”的数据。
	使用 $nor 查询时,索引并不能有效优化查询性能。因为 $nor 查询需要返回所有不匹配任意条件的文档,而不是索引中有的文档,
	这样会导致全集合扫描,对性能产生负面影响。所以在使用 $nor 查询时,应该尽量避免使用索引字段,改为使用其他字段来进行查询。

联合使用:db.user.find({key1:value1,key2:value2},{$or:[{key1:value1},{key2: value2}]}).pretty()
					where k1 = v1 and (k2 = v2 or k3 = v3)
					
· 分页:db.user.find().pretty().limit(number).Skip(number)   limit()条数,skip()跳过多少条
· 排序:db.user.find().pretty().sort({KEY:1})   1 升序, -1 降序

· $size-需要在数组字段上使用数组索引才会走索引:用于查询数组字段中元素的数量。
	有两种方式可以创建数组索引:
		1.创建普通索引:可以在数组字段上创建普通索引,这样就可以支持对整个数组的查询。
			db.collection.createIndex( { arrayField: 1 } )
				
		2.创建多元索引:可以在数组字段和数组元素的字段上创建索引,这样就可以支持对数组元素的查询。
			db.collection.createIndex( { arrayField.elementField: 1 } )
			
			需要注意的是,如果数组元素是文档类型,需要使用"."来分隔文档字段和数组元素字段:
				db.collection.createIndex( { "arrayField.elementField.subField" : 1 } )
				需要注意的是,如果你想要查询的是数组中的一个特定的元素的话,需要使用 $elemMatch 操作符来查询,而不能直接使用索引来查询,
				这样会导致扫描整个集合。
				db.collection.find( { arrayField: { $elemMatch: { elementField: value } } } )
				这样就可以利用索引加速数组元素的查询了。
	例:
		db.collection.find( { tags: { $size: 3 } } )  #查询所有tags字段数组长度为3的文档
		
· $type-不走索引:查询字段的数据类型
	MongoDB 使用以下数字编码来表示不同的数据类型:
	 	1:double
		2: string
		3: object
		4: array
		5: binary data
		6: undefined
		7: object id
		8: boolean
		9: date
		10: null
		11: regular expression
		16: int32
		18: int64
	例:
		db.collection.find( { age: { $type: 1 } } ) #查询所有age字段类型为double的文档
		
· $text -需要创建文本索引:用于在文本数据上执行全文搜索。
	创建全文索引:db.collection.createIndex({field: "text"}, { default_language: "none" })

	例:
		db.collection.find( { $text: { $search: "text search", $language: "fr" } } )
		
		MongoDB 会在所有已经建立文本索引的字段中查询 "text search"。
		$language:是需要搜索的语言,默认英语,不支持中文全文搜索,以下是两种解决方法:
		
			1.要使用第三方中文分词库或者使用第三方工具,比如 Elasticsearch 来支持中文全文搜索
			2.MongoDB 5.5 及以上版本提供了新的语言类型 "none",但它只能用于跳过语言分析,直接搜索原始的文本,这样中文就可以支持
				全文搜索了。
				db.collection.createIndex({field: "text"}, { default_language: "none" })



· $where-不走索引: 是 MongoDB 中的一个特殊查询操作符,可以在查询中使用 JavaScript 表达式。
					它允许在查询中使用更复杂的逻辑和运算符。
	例:
		db.collection.find(
		   { $where: "this.fieldName > 10" }
		)
	使用 $where 查询时, MongoDB 将每个文档传递给 JavaScript 引擎,并对其进行评估。如果评估结果为 true,则文档将包含在结果中。
	由于 $where 使用 JavaScript 表达式进行查询,因此它的性能通常比其他查询操作符要差。还需要注意的是,使用 $where 时,
	不能使用索引,因此会导致性能问题。

聚合操作:在使用聚合操作符时如$group,$match,$sort,$skip,$limit等,如果在聚合操作符后面不是使用$sort操作符,
			那么索引将不会被使用。

连表查询例子:
db.table_name.aggregate([
    {
        "$lookup": {
            "from": "task_collection",  #需要联合查询的另一张表B
            "localField": "task_id",  #表A的字段
            "foreignField": "task_id",  #表B的字段
            "as": "task_docs"  #别名
        },
    },
    {
        "$unwind":{
            "path":"$task",
             "preserveNullAndEmptyArrays":True   #不加这参数的话,副表没记录的话会丢弃该数据(左连接)
         }  #拆分,将某个列表字段拆分成多行(连表查询时,返回的是数组,使用这个就可以转化为字典,前提你得保证是唯一的)
    }
    {
        "$match":  #筛选条件
        {
            "user_id": "name"  #这里是根据表A中 user_id == name 
        }
    },
    {
        "$addFields": {  #与project异同,可以自定义字段
            "task_id": "$task_docs._id",    #如果是表字段需要加$
            "自定义字段名":"自定义字段值",
        }
    },
	{
	    "$project":  #最终需要显示哪些字段,1:显示
	    {
	        "task_docs.task_id": 1,
	        "task_docs.task_name": 1,
	        "task_docs.task_type": 1,
	        "task_docs.evidence_content": 1,
	        "case_id": 1,
	        "task_id": 1,
	        "user_id": 1,
	        "_id": 0,
	        "task_name": {
	            "$ifNull": ["$task_name", "N/A"]
	        },  #设置默认值 ,仅限$project里使用
	        "endDate": {  #例如判断日期是否有值,有值的话就格式化,否则就默认为空字符串
	            "$cond": [{
	                "$eq": ["$endDate", None]
	            }, "", {
	                          "$dateToString": {
	                              "format": "%Y-%m-%d %H:%M:%S",
	                              "date": "$endDate"
	                          }
	                      }]
	        },
	        #类似枚举功能如果 status 字段的值为 1,则会返回数组的第二个元素 "未开始";如果值为 2,则会返回数组的第三个
	        'status': {  
	            '$arrayElemAt': [["未知", "未开始", "进行中", "失败", "完成"], "$status"]
	        },
	    }
	},
	{
		#排序
		"$sort": {age: 1, name: -1}
	},
    {
	    "$skip": 2,  #偏移
    },
    {
        "$limit": 2,  #条数
    },
    {  #自定义查询结果数据结构
        "$facet": {
            "data": [{
                "$match": {}
            }, {
                "$limit": 10
            }],
            "total": [{
                "$count": "total"
            }]
        }
    },
])

#连表分页并获取总页数
db.collection.aggregate([
  {
        '$lookup': {
            'from': 'product',
            'localField': 'product',
            'foreignField': '_id',
            'as': 'product_info'
        }
    },
    {
        '$unwind': {
            'path': '$product_info',
            'preserveNullAndEmptyArrays': True
        }
    },
    {
        '$lookup': {
            'from': 'newPatientInfo',
            'localField': '_id',
            'foreignField': 'taskid',
            'as': 'new_patient'
        }
    },
    {
        '$unwind': {
            'path': '$new_patient',
            'preserveNullAndEmptyArrays': True
        }
    },
    {
        '$match': {}
    },
    {
        '$addFields': {
            'productname': '$product_info.productname',
            'period': '$product_info.period',
            'patientname': '$new_patient.patientname',
        }
    },
    {
        '$sort': {
            'checkDate': -1
        }
    },
    {
        '$facet': {
            'total': [{
                '$count': 'total'
            }],
            'data': [{
                '$skip': 0
            }, {
                '$limit': 10
            }]
        }
    }
],allowDiskUse=True)


# 查看语句执行计划,查看该语句的性能,等价于mysql的:EXPLAIN SELECT * FROM table_name WHERE condition;

db.task.aggregate([{},{}],{ explain: true })

#用于指示查询是否允许使用磁盘空间来存储中间结果。默认情况下,MongoDB 查询操作的内存限制是 100MB,
如果查询的结果集或中间结果超过这个限制,将会抛出错误。通过设置 allowDiskUse=True,你可以允许查询使用磁盘空间来存储超出内存限制的结果。当查询的结果集或中间结果比较大时,使用 allowDiskUse=True 可以避免内存限制导致的查询失败。
它允许 MongoDB 将数据存储在磁盘上的临时文件中,以便能够处理更大规模的查询。

db.task.aggregate([{},{}],{ allowDiskUse: true })

3,改

MongoDB 使用 update() 和 save() 方法来更新集合中的文档。
update()方法第一个参数是放筛选条件的,用法和上面的查一样。可以用and和or或者联合一起用,第二个参数就是需要修改的键值。

修改第一条:db.user.update({k1:v1},{$set:{k2:v2}}) 
修改全部 :  db.user.update({k1:v1},{$set:{k2:v2}},{multi:true}) 

save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。
db.col.save({k1:v1,k2v2})

4,删

MongoDB remove() 函数是用来删除集合中的数据。
db.collection.remove(
   <query>,
   <justOne>
)
如果你的 MongoDB 是 2.6 版本以后的,语法格式如下:
db.collection.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   }
)
1,query :(可选)删除的文档的条件。
2,justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
3,writeConcern :(可选)抛出异常的级别。

db.user.remove({k1:v1})
这个筛选条件同样和上面的一样,注意:如果是为空的条件,则就是删除全部,要小心!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值