MongoDB数据库简单操做

以前学过的有mysql数据库,如今咱们学习一种非关系型数据库html

1、简介

MongoDB是一款强大、灵活、且易于扩展的通用型数据库python

MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。mysql

在高负载的状况下,添加更多的节点,能够保证服务器性能。正则表达式

MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。redis

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档相似于 JSON 对象。字段值能够包含其余文档,数组及文档数组。sql

 

一、易用性mongodb

MongoDB是由C++编写的,是一个基于分布式文件存储的开源数据库系统,它不是关系型数据库。在高负载的状况下,添加更多的节点,能够保证服务器的性能。数据库

复制代码
MongoDB是一个面向文档(document-oriented)的数据库,而不是关系型数据库。
不采用关系型主要是为了得到更好得扩展性。固然还有一些其余好处,与关系数据库相比,面向文档的数据库再也不有“行“(row)
的概念取而代之的是更为灵活的“文档”(document)模型。经过在文档中嵌入文档和数组,面向文档的方法可以仅使用一条记录
来表现复杂的层级关系,这与现代的面向对象语言的开发者对数据的见解一致。
 
 
另外,再也不有预约义模式(predefined schema):文档的键(key)和值(value)再也不是固定的类型和大小
。因为没有固定的模式,根据须要添加或删除字段变得更容易了。一般因为开发者可以进行快速迭代,因此开发进程得以加快。
并且,实验更容易进行。开发者能尝试大量的数据模型,从中选一个最好的。
复制代码

 

卓越的性能编程

复制代码
MongoDB的一个主要目标是提供卓越的性能,这很大程度上决定了MongoDB的设计。MongoDB把尽量多的内存用做缓存cache,
视图为每次查询自动选择正确的索引。 总之各方面的设计都旨在保持它的高性能 虽然MongoDB很是强大并试图保留关系型数据库的不少特性,但它并不追求具有关系型数据库的全部功能。
只要有可能,数据库服务器就会将处理逻辑交给客户端
。这种精简方式的设计是MongoDB可以实现如此高性能的缘由之一
复制代码

 

 

 

2、MongoDB基础知识json

一、文档是MongoDB的核心概念。文档就是键值对的一个有序集{'msg':'hello','foo':3}。相似于python中的有序字典

须要注意的是:
#一、文档中的键/值对是有序的。
#二、文档中的值不只能够是在双引号里面的字符串,还能够是其余几种数据类型(甚至能够是整个嵌入的文档)。
#三、MongoDB区分类型和大小写。
#四、MongoDB的文档不能有重复的键。
#五、文档中的值能够是多种不一样的数据类型,也能够是一个完整的内嵌文档。文档的键是字符串。除了少数例外状况,键可使用任意UTF-8字符。

文档键命名规范:
#一、键不能含有\0 (空字符)。这个字符用来表示键的结尾。
#二、.和$有特别的意义,只有在特定环境下才能使用。
#三、如下划线"_"开头的键是保留的(不是严格要求的)。

 

 

二、集合就是一组文档。若是将MongoDB中的一个文档比喻为关系型数据的一行,那么一个集合就是至关于一张表

复制代码
#一、集合存在于数据库中,一般状况下为了方便管理,不一样格式和类型的数据应该插入到不一样的集合,但其实集合没有固定的结构,
这意味着咱们彻底能够把不一样格式和类型的数据通通插入一个集合中。 #二、组织子集合的方式就是使用“.”,分隔不一样命名空间的子集合。 好比一个具备博客功能的应用可能包含两个集合,分别是blog.posts和blog.authors,这是为了使组织结构更清晰,
这里的blog集合(这个集合甚至不须要存在)跟它的两个子集合没有任何关系。 在MongoDB中,使用子集合来组织数据很是高效,值得推荐 #三、当第一个文档插入时,集合就会被建立。合法的集合名: 集合名不能是空字符串""。 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。 集合名不能以"system."开头,这是为系统集合保留的前缀。 用户建立的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是由于某些系统生成的集合中包含该字符。
除非你要访问这种系统建立的集合,不然千万不要在名字里出现$。
复制代码

三、数据库:在MongoDB中,多个文档组成集合,多个集合能够组成数据库

复制代码
数据库也经过名字来标识。数据库名能够是知足如下条件的任意UTF-8字符串:
#一、不能是空字符串("")。
#二、不得含有' '(空格)、.、$、/、\和\0 (空字符)。
#三、应所有小写。
#四、最多64字节。

有一些数据库名是保留的,能够直接访问这些有特殊做用的数据库。
#一、admin: 从身份认证的角度讲,这是“root”数据库,若是将一个用户添加到admin数据库,这个用户将自动得到全部数据库的权限。再者,一些特定的服务器端命令也只能从admin数据库运行,如列出全部数据库或关闭服务器
#二、local: 这个数据库永远都不能够复制,且一台服务器上的全部本地集合均可以存储在这个数据库中
#三、config: MongoDB用于分片设置时,分片信息会存储在config数据库
复制代码

四、强调:把数据库名添加到集合名前,获得集合的彻底限定名,即命名空间

例如:
若是要使用cms数据库中的blog.posts集合,这个集合的命名空间就是
cms.blog.posts。命名空间的长度不得超过121个字节,且在实际使用中应该小于100个字节

基本数据类型:

基于BSON结构
    string     字符串,Utf8
    integer    整型
    double    双精度,包含float,MongoDB中不存在Float
    Null    空数据类型
    Date    时间类型 ISODate(2018-9-12 10:45:58)
    Timestamp 时间戳类型 ISODate("123123")
    
    ObjectId    对象ID    Documents 自生成的 _id ObjectId("5b98794ec34b9812bcabdde7")
                #"5b151f85"     代指的是时间戳,这条数据的产生时间
                #"364098"         代指某台机器的机器码,存储这条数据时的机器编号
                #"09ab"         代指进程ID,多进程存储数据的时候,很是有用的
                #"2e6b26"         代指计数器,这里要注意的是,计数器的数字可能会出现重复,不是惟一的
                #以上四种标识符拼凑成世界上惟一的ObjectID
                #只要是支持MongoDB的语言,都会有一个或多个方法,对ObjectID进行转换
                #能够获得以上四种信息
基本数据类型

 

 

3、安装

 

 

(此处说的是windows的)

下载好mongoDB以后,选择文件夹安装 ,而后配置环境变量,就是把你的环境变量配置到电脑上,而后你须要再创建一个文件夹用来存放mpongodb的数据库

 

 

安装目录:
    D:\MongoDB
    而后找到bin目录加入到电脑的环境变量种


  而后再建立一个目录用来存放你的数据库
    
            D:\MongoDB\data\db
目录一半都是建立data\db

而后这个时候用你的管理员的身份来运行cmd而后切换到你的 新创建的存放数据库的文件夹下:
D:\MongoDB\data\db
    而后执行 mongod --dbpath +你的文件夹路径
    mongod --dbpath D:\MongoDB\data\db
    就把你的数据库链接打开了  


而后你就能够经过其余链接 进行与你的mongodb数据库链接了(切忌:上一次的和数据库的连接不能够断开 就是选定的连接文件夹和数据库相链接)

 

选好安装目录
D:\MongoDB
选择数据库存放目录
D:\MongoDB\data\db
以管理员身份运行
mongod --dbpath D:\MongoDB\data\db 

 

而后再次打开新的链接   上次的连接不能够断开 须要再次打开新的连接进行数据库访问

 

 

二、帐号管理

 

复制代码
#帐号管理:https://docs.mongodb.com/master/tutorial/enable-authentication/
#一、建立有权限的用户

  use admin
  db.createUser(
    { 
      user: "root", #这个root能够随便写
      pwd: "123", 
      roles: [ { role: "root", db: "admin" } ] #权限,role是root说明是管理员,
    }
  )

 
 

  use test
  db.createUser(
    {
      user: "egon",
      pwd: "123", 
      roles: [ { role: "readWrite", db: "test" }, #针对test库有读写权限,操做本身的库有读写权限
      { role: "read", db: "db1" } ] #针对db1库读权限,操做其余库有读权限
    }
  )

#二、重启数据库
mongod --remove
mongod --config "C:\mongodb\mongod.cfg" --bind_ip 0.0.0.0 --install --auth
或者
mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath
D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install --auth

#三、登陆:注意使用双引号而非单引号 mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin" 也能够在登陆以后用db.auth("帐号","密码")登陆 mongo use admin db.auth("root","123") #推荐博客:https://www.cnblogs.com/zhoujinyi/p/4610050.html 建立帐号密码+开启认证机制
复制代码

 

 

 

 

数据库的链接工具:

连接:https://robomongo.org/

 

简单操做:

 

 

以上是一个简单的链接工具,就是先链接本机的数据库 也能够选择链接其余ip地址的数据库(仅仅限于mongoDB数据库)

 

 

在mongodb种数据库仍是数据库的含义,可是表的定义没有了,叫集合(其实仍是表)

基本数据类型

一、在概念上,MongoDB的文档与Javascript的对象相近,于是能够认为它相似于JSON。JSON(http://www.json.org)是一种简单的数据表示方式:其规范仅用一段文字就能描述清楚(其官网证实了这点),且仅包含六种数据类型。

二、这样有不少好处:易于理解、易于解析、易于记忆。然而从另外一方面说,由于只有null、布尔、数字、字符串、数字和对象这几种数据类型,因此JSON的表达能力有必定的局限。

三、虽然JSON具有的这些类型已经具备很强的表现力,但绝大数应用(尤为是在于数据库打交道时)都还须要其余一些重要的类型。例如,JSON没有日期类型,这使得本来容易日期处理变得烦人。另外,JSON只有一种数字类型,没法区分浮点数和整数,更别区分32位和64位了。再者JSON没法表示其余一些通用类型,如正则表达式或函数。

四、MongoDB在保留了JSON基本键/值对特性的基础上,添加了其余一些数据类型。在不一样的编程语言下,这些类型的确切表示有些许差别。下面说明了MongoDB支持的其余通用类型,以及如何正在文档中使用它们

五、数据类型

 1 #一、null:用于表示空或不存在的字段
 2 d={'x':null}
 3 #二、布尔型:true和false
 4 d={'x':true,'y':false}
 5 #三、数值
 6 d={'x':3,'y':3.1415926}
 7 #四、字符串
 8 d={'x':'egon'}
 9 #五、日期
10 d={'x':new Date()}
11 d.x.getHours()
12 #六、正则表达式
13 d={'pattern':/^egon.*?nb$/i}
14 
15 正则写在//内,后面的i表明:
16 i 忽略大小写
17 m 多行匹配模式
18 x 忽略非转义的空白字符
19 s 单行匹配模式
20 
21 #七、数组
22 d={'x':[1,'a','v']}
23 
24 #八、内嵌文档
25 user={'name':'egon','addr':{'country':'China','city':'YT'}}
26 user.addr.country
27 
28 #九、对象id:是一个12字节的ID,是文档的惟一标识,不可变
29 d={'x':ObjectId()}
数据类型

 

 

六、_id和ObjectId

1 MongoDB中存储的文档必须有一个"_id"键。这个键的值能够是任意类型,默认是个ObjectId对象。
 2 在一个集合里,每一个文档都有惟一的“_id”,确保集合里每一个文档都能被惟一标识。
 3 不一样集合"_id"的值能够重复,但同一集合内"_id"的值必须惟一
 4 
 5 #一、ObjectId
 6 ObjectId是"_id"的默认类型。由于设计MongoDb的初衷就是用做分布式数据库,因此可以在分片环境中生成
 7 惟一的标识符很是重要,而常规的作法:在多个服务器上同步自动增长主键既费时又费力,这就是MongoDB采用
 8 ObjectId的缘由。
 9 ObjectId采用12字节的存储空间,是一个由24个十六进制数字组成的字符串
10     0|1|2|3|   4|5|6|     7|8    9|10|11    
11     时间戳      机器      PID    计数器
12 若是快速建立多个ObjectId,会发现每次只有最后几位有变化。另外,中间的几位数字也会变化(要是在建立过程当中停顿几秒)。
13 这是ObjectId的建立方式致使的,如上图
14 
15 时间戳单位为秒,与随后5个字节组合起来,提供了秒级的惟一性。这个4个字节隐藏了文档的建立时间,绝大多数驱动程序都会提供
16 一个方法,用于从ObjectId中获取这些信息。
17 
18 由于使用的是当前时间,不少用户担忧要对服务器进行时钟同步。其实不必,由于时间戳的实际值并不重要,只要它老是不停增长就好。
19 接下来3个字节是所在主机的惟一标识符。一般是机器主机名的散列值。这样就能够保证不一样主机生成不一样的ObjectId,不产生冲突
20 
21 接下来连个字节确保了在同一台机器上并发的多个进程产生的ObjectId是惟一的
22 
23 前9个字节确保了同一秒钟不一样机器不一样进程产生的ObjectId是惟一的。最后3个字节是一个自动增长的 计数器。确保相同进程的同一秒产生的
24 ObjectId也是不同的。
25 
26 #二、自动生成_id
27 若是插入文档时没有"_id"键,系统会自帮你建立 一个。能够由MongoDb服务器来作这件事。
28 但一般会在客户端由驱动程序完成。这一作法很是好地体现了MongoDb的哲学:能交给客户端驱动程序来作的事情就不要交给服务器来作。
29 这种理念背后的缘由是:即使是像MongoDB这样扩展性很是好的数据库,扩展应用层也要比扩展数据库层容易的多。将工做交给客户端作就
30 减轻了数据库扩展的负担。
_id 和objectid

 

5、增删改查操做

增删改查:

 

增:
    - db.user.info  #user.info表
    - db.user #user表
    - db.user.auth  ##user.auth表

  当第一个文档插入时,集合就会被建立
  > use database1
  switched to db database1
  > db.table1.insert({'a':1})
  WriteResult({ "nInserted" : 1 })
  > db.table2.insert({'b':2})
  WriteResult({ "nInserted" : 1 })
查:
    - show collections
    - show tables  #这两个是同样的
    #只要是空不显示
删:
    - db.user.info.help()  #查看帮助
    - db.user.info.drop()

 

 

 

一、数据库的增:

 

增长数据库:
    use +数据库名   # 有则切换无则新增

    当你用use 建立完以后,你须要在insert以后才能显示出这个数据库

    db.建立的数据库名.insertOne()
    eg:
    db.db.insertOne() 而后就会显示出你所建立的数据库

    或者你直接使用db.建立的数据库名.insertOne()而后也能够直接建立出数据库

 

mongodb数据库的操做不论事增、删、改、查 都是须要用到db.你的数据的名而后再加上要操做的内容

你使用use建立的只是数据库 而当你插入第一条数据的时候你的集合就会被建立

 

 

 

建立数据库 use+数据库名 有则切换 无则建立
查看服务器中的全部的数据库 show  dbs  
db 查看当前所在的数据库  
show tables  查看当前数据库的中的集合  

 

一、集合的增长insert

 

增长 db.test.insert({"name":"老王"}) 这个是对你的数据中插入一个集合为test的数据
多行增长 db.test.insert([{"name":"隔壁老王"},{"hobby":"找人"}]) 对你的数据库中的test集合插入两条数据 
     
单行增长 db.db.inertOne({"name":"隔壁老王"})  为你的数据中插入一个集合为db的数据 
多行插入 d.db.insertMany([{"name":"隔壁老王"},{"name":"你媳妇"}])  为你的数据库中插入一个集合 db,db集合中有两条数据 
     


增:

#一、没有指定_id则默认ObjectId,_id不能重复,且在插入后不可变
 2 
 3 #二、插入单条
 4 user0={
 5     "name":"egon",
 6     "age":10,
 7     'hobbies':['music','read','dancing'],
 8     'addr':{
 9         'country':'China',
10         'city':'BJ'
11     }
12 }
13 
14 db.test.insert(user0)
15 db.test.find()
16 
17 #三、插入多条
18 user1={
19     "_id":1,
20     "name":"alex",
21     "age":10,
22     'hobbies':['music','read','dancing'],
23     'addr':{
24         'country':'China',
25         'city':'weifang'
26     }
27 }
28 
29 user2={
30     "_id":2,
31     "name":"wupeiqi",
32     "age":20,
33     'hobbies':['music','read','run'],
34     'addr':{
35         'country':'China',
36         'city':'hebei'
37     }
38 }
39 
40 
41 user3={
42     "_id":3,
43     "name":"yuanhao",
44     "age":30,
45     'hobbies':['music','drink'],
46     'addr':{
47         'country':'China',
48         'city':'heibei'
49     }
50 }
51 
52 user4={
53     "_id":4,
54     "name":"jingliyang",
55     "age":40,
56     'hobbies':['music','read','dancing','tea'],
57     'addr':{
58         'country':'China',
59         'city':'BJ'
60     }
61 }
62 
63 user5={
64     "_id":5,
65     "name":"jinxin",
66     "age":50,
67     'hobbies':['music','read',],
68     'addr':{
69         'country':'China',
70         'city':'henan'
71     }
72 }
73 db.user.insertMany([user1,user2,user3,user4,user5])

 

 

二、集合的删

删:db.dropDatabase()  #

db.user.drop() #删除user集合

db.user.remove({})
// remove 方式 被官方不推荐了
db.user.deleteOne({"name":"白虎"})
db.user.deleteMany({"name":"翠花儿"})

 

 

1 #一、删除多个中的第一个
2 db.user.deleteOne({ 'age': 8 })
3 
4 #二、删除国家为China的所有    这个是删除你的全部的知足条件的
5 db.user.deleteMany( {'addr.country': 'China'} ) 
6 
7 #三、删除所有
8 db.user.deleteMany({})

 

 

可视化工具

连接:https://robomongo.org/

 

 

三、查 find

db.+集合名.find()  #查看这个集合内部的全部内容

db.test.find()  #查看test集合中的全部内容



根据条件查找
db.test.find(条件)

db.test.find("name":"老王")  #查找test集合中的name是老王的信息

findOne()  查找单行
db.one.findOne({"name":"老王",age:1})  逗号表明and

 

 

 

数字比较符:

$lt 
小于
$gt
大于
$lte 
小于等于
$gte
大于等于

 

$and  和
$or 或者
$not 不是
$mod 取模运算

 

 

$gt  大于

db.test.findOne({"id":{$gt:1}})  求集合test中id大于1的信息


$lt 小于
db.test.findOne({"id":{$lt:5}}) 集合test中id小于5的信息


$lte小于等于
db.test.findOne({"id":{$lte:3}}) 集合test中id小于等于5的信息


$gte 大于等于

 db.user.find({
      "_id":{"$gte":3,"$lte":4},
      "age":{"$gte":40}  #结束就不要加逗号了
  })


$and # 并列查询 以逗号分隔
db.user.find({"$and":[
     {"_id":{"$gte":3,"$lte":4}},  #一个字典就是一个条件
     {"age":{"$gte":40}}
 ]}
 
 
select * from db1.user where id >=0 and id <=1 or id >=4 or name = "yuanhao";
 db.user.find({"$or":[
 {"_id":{"$lte":1,"$gte":0}},
 {"_id":{"$gte":4}},
 {"name":"yuanhao"}
 ]})
 
 
 select * from db1.user where id % 2 = 1;  #奇数
 db.user.find({"_id":{"$mod":[2,1]}})  #取模运算,id对2取模
 
 #取反,偶数
 db.user.find({
     "_id":{"$not":{"$mod":[2,1]}}
 })



 

 

$in 在里面
$nin 不在
   

 

# SQL:in,not in
2 # MongoDB:"$in","$nin"
3 
4 #一、select * from db1.user where age in (20,30,31);
5 db.user.find({"age":{"$in":[20,30,31]}})
6 
7 #二、select * from db1.user where name not in ('huahua','xxx');
8 db.user.find({"name":{"$nin":['hauhua','xxx']}})
$in 在什么里面
$or 或者
$all 必需要包含全部的
$in: db.user.find({age:{$in:[1,2,3]}}) 字段符合in,array中的数值

$or: db.user.find({$or:[{age:{$in:[1,2,3,4]}},{name:666}]})

$all: db.user.find({test:{$all:[1,2]}}) array元素相同便可 或 包含全部$all中的元素

 

 

 

 

改:update

1 update() 方法用于更新已存在的文档。语法格式以下:
 2 db.collection.update(
 3    <query>,
 4    <update>,
 5    {
 6      upsert: <boolean>,
 7      multi: <boolean>,
 8      writeConcern: <document>
 9    }
10 )
11 参数说明:对比update db1.t1 set name='EGON',sex='Male' where name='egon' and age=18;
12 
13 query : 至关于where条件。
14 update : update的对象和一些更新的操做符(如$,$inc...等,至关于set后面的
15 upsert : 可选,默认为false,表明若是不存在update的记录不更新也不插入,设置为true表明插入。
16 multi : 可选,默认为false,表明只更新找到的第一条记录,设为true,表明更新找到的所有记录。
17 writeConcern :可选,抛出异常的级别。
18 
19 更新操做是不可分割的:若两个更新同时发送,先到达服务器的先执行,而后执行另一个,不会破坏文档。
updat语法介绍

 

 

$set : 将某个key的value 修改成 某值
    $unset: 删除字段 {$unset: {test: "" }}
    
    $inc:{$inc:{"age":100}} 原有值基础上增长 xxx
    
    array:
    $push : 向数组Array最后位置插入一条元素 {$push:{"hobby":1234}} [].append(1234)
    $pull : 删除数组中的某一个元素 {$pull:{"hobby":123}} 
            #删除字典 db.user.updateOne({"_id":ObjectId("5b98794ec34b9812bcabdde7"),"hobby.age":18},{$unset:{"hobby.$":1}})    
    $pop : 删除数组的第一个或最后一个  
        最后一个:{$pop:{"hobby":1}} 
        第一个:{$pop:{"hobby":-1}} 
        
    $ :代指符合条件的某数据  array.$ :
        db.user.updateOne({"_id":ObjectId("5b98794ec34b9812bcabdde7"),"hobby.name":"翠花儿"},{$set:{"hobby.$.name":"农妇山泉"}})
                                                         后面条件的$带表指的是前面的条件 就是告诉你要修改的是前面的条件

 

 

 

update修改:

updateOne  修改单条

db.test.updateOne({"name":"隔壁小姑娘"},{"name":"操场小妹妹"})

updateMany #修改多条数据

 

修改器:$set

 

$set 讲某个key的value修改成某值
$unset 删除字段 {$unset: {test: "" }}
$inc 在原值上增长
$push 向数组Array最后位置插入一条元素
$pull 删除数组中的某一个元素
$pop  删除数组的第一个或最后一个  
$ 单独使用代指的是你的条件
   

 

db.test.update({"name":"操场小妹妹"},{"$set":{"name":"属于你的妹子"}}) 修改

修改单挑数据

 db.user.updateOne({"name":"子龙"},{$set:{"name":"赵子龙"}})

修改多条数据
 db.user.updateMany({"name":"小青龙"},{$set:{"name":"白虎"}})

 




 

混搭:

 排序 跳过 显示条目
sort 排序 find().sort(id:-1/1) 1 升序 2 降序 desc
skip 跳过 find().skip(2) 从三条开始返回
limit 显示条目 find().limit(2)只显示前两条

混搭:
db.user.find({}).sort({age:-1 }).skip(1).limit(2)
根据age字段进行降序排列,而且跳过第一条,从第二条开始返回,两条数据

 

在python中上面的deleteone 都会变成delte_one 都会变成下划线之类的

res = mongo_db.user.find_one({"_id":ObjectId("5b98794ec34b9812bcabdde7")})

查找单条的数据

res = mongo_db.content.insert_one({"name":"123"}) 插入单条

res = mongo_db.content.update_one({"name":"123"},{"$set":{"name":"666"}}) 修改单条

修改多条
res = mongo_db.content.update_many({"name":"666"},{"$set":{"name":"123"}})

 

 

 

mondoDB和python的链接:

 

 

首先要先安装pymongo 模块

pip3 install pymongo

 

python和mongodb数据库链接

.MongoDB的默认端口号:27017  (redis:6379 MySql:3306)

mclient = pymongo.MongoClient(host="127.0.0.1", port=27017)  #端口号和地址
mongo_db = mclient[数据库]



========
client=MongoClient('mongodb://root:123@localhost:27017')
table=client['db1']['emp']
相关文章
相关标签/搜索