22.4.3.3 查找文档
您可以使用 find()
方法来查询并返回集合中的文档。MySQL Shell 提供了额外的方法,可以与 find()
方法一起使用,以便筛选和排序返回的文档。
MySQL 提供以下运算符来指定搜索条件:OR
(||
),AND
(&&
),XOR
,IS
,NOT
,BETWEEN
,IN
,LIKE
,!=
,<>
,>
,>=
,<
,<=
,&
,|
,<<
,>>
,+
,-
,*
,/
,~
,和 %
。
要返回集合中的所有文档,请不指定搜索条件并使用 find()
方法。例如,以下操作会返回集合 countryinfo
中的所有文档。
mysql-py> db.countryinfo.find()
[
{
"GNP": 828,
"Code:": "ABW",
"Name": "Aruba",
"IndepYear": null,
"geography": {
"Continent": "North America",
"Region": "Caribbean",
"SurfaceArea": 193
},
"government": {
"GovernmentForm": "Nonmetropolitan Territory of The Netherlands",
"HeadOfState": "Beatrix"
}
"demographics": {
"LifeExpectancy": 78.4000015258789,
"Population": 103000
},
...
}
]
240 documents in set (0.00 sec)
该方法产生包含操作信息在文档列表之后的结果集。
如果没有匹配的文档(空集),则返回以下信息:
Empty set (0.00 sec)
您可以将搜索条件与 find()
方法一起使用。用于构成搜索条件的表达式语法与传统 MySQL 第14章 函数和运算符 中描述的一样。所有表达式都必须用引号括起来。为了简洁起见,部分示例未显示输出。
一个简单的搜索条件可能包括 Name
字段和我们知道存在于某个文档中的值。以下示例返回单个文档:
mysql-py> db.countryinfo.find("Name = 'Australia'")
[
{
"GNP": 351182,
"Code:": "AUS",
"Name": "Australia",
"IndepYear": 1901,
"geography": {
"Continent": "Oceania",
"Region": "Australia and New Zealand",
"SurfaceArea": 7741220
},
"government": {
"GovernmentForm": "Constitutional Monarchy, Federation",
"HeadOfState": "Elisabeth II"
}
"demographics": {
"LifeExpectancy": 79.80000305175781,
"Population": 18886000
},
}
]
以下示例搜索所有GNP大于500亿美元的国家。集合 countryinfo
测量 GNP 单位为百万美元。
mysql-py> db.countryinfo.find("GNP > 500000")
...[output removed]
10 documents in set (0.00 sec)
在以下查询中,Population 字段嵌入在 demographics 对象中。要访问嵌套字段,请使用点号来识别关系。文档和字段名是大小写敏感的。
mysql-py> db.countryinfo.find("GNP > 500000 and demographics.Population < 100000000")
...[output removed]
6 documents in set (0.00 sec)
以下表达式中的算术运算符用于查询 GNP 人均值大于30000美元的国家。搜索条件可以包含算术运算符和大多数 MySQL 函数。
集合 countryinfo
中有七个文档的 Population 值为零,因此在输出末尾出现警告消息。
mysql-py> db.countryinfo.find("GNP*1000000/demographics.Population > 30000")
...[output removed]
9 documents in set, 7 warnings (0.00 sec)
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
您可以通过使用 bind()
方法将值与搜索条件分开。例如,代替硬编码国家名称作为条件,可以使用以字母开头的命名占位符(冒号后跟一个名字),如 country。然后,在程序中使用 bind(
方法如下所示:placeholder
, value
)
mysql-py> db.countryinfo.find("Name = :country").bind("country", "Italy")
{
"GNP": 1161755,
"_id": "00005de917d8000000000000006a",
"Code": "ITA",
"Name": "Italy",
"Airports": [],
"IndepYear": 1861,
"geography": {
"Region": "Southern Europe",
"Continent": "Europe",
"SurfaceArea": 301316
},
"government": {
"HeadOfState": "Carlo Azeglio Ciampi",
"GovernmentForm": "Republic"
},
"demographics": {
"Population": 57680000,
"LifeExpectancy": 79
}
}
1 document in set (0.01 sec)
在程序中,绑定允许您在表达式中指定占位符,这些占位符在执行之前会被值填充,并且可以从自动转义中受益,如适当。
始终使用绑定来清理输入。避免通过字符串连接将值插入查询中,这可能产生无效的输入,并在某些情况下可能导致安全问题。
您可以使用占位符和 bind()
方法创建保存搜索的查询,然后用不同的值调用它们。例如,要创建一个国家的保存搜索:
mysql-py> myFind = db.countryinfo.find("Name = :country")
mysql-py> myFind.bind('country', 'France')
{
"GNP": 1424285,
"_id": "00005de917d80000000000000048",
"Code": "FRA",
"Name": "France",
"IndepYear": 843,
"geography": {
"Region": "Western Europe",
"Continent": "Europe",
"SurfaceArea": 551500
},
"government": {
"HeadOfState": "Jacques Chirac",
"GovernmentForm": "Republic"
},
"demographics": {
"Population": 59225700,
"LifeExpectancy": 78.80000305175781
}
}
1 document in set (0.0028 sec)
mysql-py> myFind.bind('country', 'Germany')
{
"GNP": 2133367,
"_id": "00005de917d80000000000000038",
"Code": "DEU",
"Name": "Germany",
"IndepYear": 1955,
"geography": {
"Region": "Western Europe",
"Continent": "Europe",
"SurfaceArea": 357022
},
"government": {
"HeadOfState": "Johannes Rau",
"GovernmentForm": "Federal Republic"
},
"demographics": {
"Population": 82164700,
"LifeExpectancy": 77.4000015258789
}
}
1 document in set (0.0026 sec)
您可以返回特定字段的文档,而不是返回所有字段。以下示例返回名为 countryinfo
集合中满足搜索条件的所有文档的 GNP 和 Name 字段。
使用 fields()
方法来传递要返回的字段列表。
mysql-py> db.countryinfo.find("GNP > 5000000").fields(["GNP", "Name"])
[
{
"GNP": 8510700,
"Name": "United States"
}
]
1 document in set (0.00 sec)
此外,您可以通过表达式对返回的文档进行修改,添加、重命名、嵌套甚至计算新字段值。例如,将以下表达式用于返回两个文档的名称字段:
mysql-py> db.countryinfo.find().fields(
mysqlx.expr('{"Name": upper(Name), "GNPPerCapita": GNP*1000000/demographics.Population}')).limit(2)
{
"Name": "ARUBA",
"GNPPerCapita": 8038.834951456311
}
{
"Name": "AFGHANISTAN",
"GNPPerCapita": 263.0281690140845
}
您可以使用 limit()
、sort()
和 skip()
方法来管理 find()
方法返回的文档数量和顺序。
要指定结果集中的文档数目,向 find()
方法追加 limit()
方法,并将其与值一起使用。以下查询返回 countryinfo
集合的前五个文档。
mysql-py> db.countryinfo.find().limit(5)
... [output removed]
5 documents in set (0.00 sec)
要指定结果顺序,向 find()
方法追加 sort()
方法,并将其与一个或多个字段列表和可选的降序 (desc
) 或升序 (asc
) 属性一起使用。升序是默认顺序类型。
例如,以下查询按 IndepYear 字段排序所有文档,并以降序返回前八个文档。
mysql-py> db.countryinfo.find().sort(["IndepYear desc"]).limit(8)
... [output removed]
8 documents in set (0.00 sec)
默认情况下,limit()
方法从集合的第一个文档开始。您可以使用 skip()
方法更改起始文档。例如,要忽略第一个文档并返回接下来的八个满足条件的文档,请将 1 作为 skip()
方法的值传递。
mysql-py> db.countryinfo.find().sort(["IndepYear desc"]).limit(8).skip(1)
... [output removed]
8 documents in set (0.00 sec)
-
MySQL 参考手册(Chapter 14 Functions and Operators)提供了详细的函数和操作符文档。
-
查看 CollectionFindFunction 以获取完整语法定义。