文档主页
X DevAPI 用户指南
下载本手册
PDF (US Ltr) - 1.4Mb
PDF (A4) - 1.4Mb


X DevAPI 用户指南  /  ...  /  Collection.find()

4.3.2 Collection.find()

The find(SearchConditionStr) 函数用于搜索集合中的文档,类似于 SQL 数据库的 SELECT 语句。它使用搜索条件字符串 (SearchConditionStr) 作为参数,以指定应从数据库中返回的文档。The execute() 函数触发 find() 操作的实际执行。

The SearchConditionStr 可以采用以下几种形式

  • 如果没有指定 SearchConditionStrfind() 操作将返回集合中的所有文档。

    // Get a collection
    var myColl = session.getSchema("world_x").getCollection("countryinfo");
    // To return all documents in world_x: 
    myColl.find().execute();
  • The SearchConditionStr 的最常见形式是

    JSON-path [ operator { value | JSON-path} ]

    以下是有关 SearchConditionStr 中不同部分的解释

    • JSON-path: JSON 路径标识 JSON 文档中的元素;有关详细信息,请参阅 JSON 路径语法。以下是对 JSON 路径语法的简要总结

      • JSON 路径以范围开头:在 MySQL 的 JSON 文档实现中,路径的范围始终是正在操作的文档,表示为 $,该范围始终隐式假定,因此在大多数情况下可以省略;例如,路径 $.geography.Region 等效于 geography.Region

        注意

        在某些情况下,$ 无法省略;例如

        • 当使用 ** 通配符时(例如,find("$**.b1");请参阅下面有关通配符的讨论),

        • 当 JSON 路径仅包含一个文字字符串时,如果省略了 $(例如,find("$.'country_name'") 用于查找所有具有 country name 字段的文档)。

      • 在范围之后,路径由一个或多个路径段组成。路径段从 JSON 树的一级向下指向下一级,连续路径由点号 (.) 分隔。例如:myColl.find("geography.Continent = 'Africa'") 查找所有在 geography 字段下的 Continent 字段中具有值 Africa 的文档。

      • 数组中的元素由 [N] 表示,其中 N 是数组索引,必须为非负整数。

        myColl.add({ name:'John', favorNums: [1, 3, 5, 7, 9] }).execute();
        myColl.find("favorNums[0] = 1").execute(); //Returns the document just added
        }
    • 通配符标记 *** 可以按如下方式在 JSON 路径中使用

      • object.* 表示成员 object 下所有成员的值。例如,在示例 world_x 模式中的 countryinfo 集合中, geography.* 表示 geography 对象下的所有成员,并且 myColl.find("'Africa' in geography.*") 返回所有在 geography 下的任何成员中具有值 Africa 的文档。

      • array[*] 表示数组中所有元素的值。例如

        myColl.add({ name:'John', favorNums: [1, 3, 5, 7, 9] }).execute();
        myColl.add({ name:'Jane', favorNums: [2, 4, 6, 8, 10] }).execute();
        myColl.find("1 in favorNums[*]").execute(); //Returns the first document added above
        myColl.find("2 in favorNums[*]").execute(); //Returns the second document added above
        }
      • [prefix]**suffix 表示文档 prefix 下以 suffix 结尾的所有路径,无论路径的深度如何。以下示例说明了如何使用 ** 返回不同的结果

        mysql-js> myColl.find().execute();
        {
            "a": "bar",
            "b": {
                "b1": 6,
                "b2": 7,
                "b3": {
                    "b1": 99,
                    "b2": 98,
                    "b3": {
                        "b1": 999,
                        "b2": 998
                    }
                }
            },
            "_id": "000061313aa10000000000000001"
        }
        {
            "a": "baz",
            "b": {
                "b1": 1,
                "b2": 7
            },
            "_id": "000061313aa10000000000000002"
        }
        {
            "a": "bbr",
            "c": 37,
            "_id": "0000613247ed0000000000000001"
        }
        3 documents in set (0.0007 sec)
        mysql-js> myColl.find("$**.b2").execute();
        {
            "a": "bar",
            "b": {
                "b1": 6,
                "b2": 7,
                "b3": {
                    "b1": 99,
                    "b2": 98,
                    "b3": {
                        "b1": 999,
                        "b2": 998
                    }
                }
            },
            "_id": "000061313aa10000000000000001"
        }
        {
            "a": "baz",
            "b": {
                "b1": 1,
                "b2": 7
            },
            "_id": "000061313aa10000000000000002"
        }
        2 documents in set, 1 warning (0.0008 sec)
        ...
        mysql-js> myColl.find("$**.b3**.b2").execute();
        {
            "a": "bar",
            "b": {
                "b1": 6,
                "b2": 7,
                "b3": {
                    "b1": 99,
                    "b2": 98,
                    "b3": {
                        "b1": 999,
                        "b2": 998
                    }
                }
            },
            "_id": "000061313aa10000000000000001"
        }
        1 document in set, 1 warning (0.0011 sec)
        ...

        使用 ** 通配符时,适用以下要求

        • prefix 应为 $ 或本身为文档的元素。

        • suffix 应为路径段,并且始终是必需的(即,路径表达式不能以 ** 结尾)。

        • 路径表达式不能包含序列 ***

    • value 是要与 JSON-path 上的元素进行比较的值。The %_ 通配符字符可以在 value 中与 LIKE 运算符一起使用,就像在 MySQL WHERE 子句中一样。例如

      myColl.find("Name LIKE 'Austra%'")
      myColl.find("geography.Continent LIKE 'Asi_'")
    • operator: 以下运算符可在 SearchConditionStr 中使用:OR (||), AND (&&), XOR, IS, NOT, BETWEEN, IN, LIKE, OVERLAPS, !=, <>, >, >=, <, <=, &, |, <<, >>, +, -, *, /, ~%。以下是一些使用运算符的示例

      myColl.find("Name = 'Australia'")
      myColl.find("demographics.Population >= 1000000" )
      myColl.find("demographics.LifeExpectancy BETWEEN 50  AND 60")
      myColl.find("government.HeadOfState = 'Elizabeth II' AND geography.Region = 'Caribbean'")

      如果没有提供运算符和后续 JSON 路径,则 find() 将返回所有 JSON 路径指向某些非空元素的文档。例如

      myColl.find("demographics.Population" ).execute();

      返回所有具有 demographics.Population 元素的文档

      {
          "GNP": 828,
          "_id": "00005de917d80000000000000000",
          "Code": "ABW",
          "Name": "Aruba",
          "IndepYear": null,
          "geography": {
              "Region": "Caribbean",
              "Continent": "North America",
              "SurfaceArea": 193
          },
          "government": {
              "HeadOfState": "Beatrix",
              "GovernmentForm": "Nonmetropolitan Territory of The Netherlands"
          },
          "demographics": {
              "Population": 103000,
              "LifeExpectancy": 78.4000015258789
          }
      }
      {
          "GNP": 5976,
          "_id": "00005de917d80000000000000001",
      ...
      232 documents in set, 1 warning (0.0013 sec)
      Warning (code 3986): Evaluating a JSON value in SQL boolean context does an implicit comparison against JSON integer 0;
      if this is not what you want, consider converting JSON to an SQL numeric type with JSON_VALUE RETURNING

      SearchConditionStr 中使用 IN 运算符检查通配符涵盖的所有成员中的值

      mysql-js> myColl.find("$**.b1").execute();
      {
          "a": "bar",
          "b": {
              "b1": 6,
              "b2": 7,
              "b3": {
                  "b1": 99,
                  "b2": 98,
                  "b3": {
                      "b1": 999,
                      "b2": 998
                  }
              }
          },
          "_id": "000061313aa10000000000000001"
      }
      {
          "a": "baz",
          "b": {
              "b1": 1,
              "b2": 7
          },
          "_id": "000061313aa10000000000000002"
      }
      2 documents in set, 1 warning (0.0012 sec)
      ...
      mysql-js> myColl.find("99 IN $**.b1").execute();
      {
          "a": "bar",
          "b": {
              "b1": 6,
              "b2": 7,
              "b3": {
                  "b1": 99,
                  "b2": 98,
                  "b3": {
                      "b1": 999,
                      "b2": 998
                  }
              }
          },
          "_id": "000061313aa10000000000000001"
      }
      1 document in set (0.0016 sec)
      ...

      The OVERLAPS 运算符比较两个 JSON 片段,如果两个片段在任何键值对或数组元素中具有任何共同的值,则返回真 (1)。例如

      mysql-js> myColl.find("list").execute();
      {
          "_id": "1",
          "list": [
              1,
              4
          ]
      }
      {
          "_id": "2",
          "list": [
              4,
              7
          ]
      }
      2 documents in set, 1 warning (0.0010 sec)
      mysql-js> myColl.find("[1,2,3] OVERLAPS $.list")
      {
          "_id": "1",
          "list": [
              1,
              4
          ]
      }
      1 document in set (0.0006 sec)

可以将 fields()sort()limit() 等多种方法链接到 find() 函数,以进一步细化结果。例如

myColl.find("Name LIKE 'Austra%'").fields("Code")
myColl.find("geography.Continent LIKE 'A%'").limit(10)

也支持使用 bind() 进行参数绑定。以下示例说明了 bind()find() 的用法

MySQL Shell JavaScript 代码

// Use the collection 'my_collection'
var myColl = db.getCollection('my_collection');

// Find a single document that has a field 'name' that starts with 'L'
var docs = myColl.find('name like :param').
            limit(1).bind('param', 'L%').execute();

print(docs.fetchOne());

// Get all documents with a field 'name' that starts with 'L'
docs = myColl.find('name like :param').
        bind('param','L%').execute();

var myDoc;
while (myDoc = docs.fetchOne()) {
  print(myDoc);
}

MySQL Shell Python 代码

# Use the collection 'my_collection'
myColl = db.get_collection('my_collection')

# Find a single document that has a field 'name' that starts with 'L'
docs = myColl.find('name like :param').limit(1).bind('param', 'L%').execute()

print(docs.fetch_one())

# Get all documents with a field 'name' that starts with 'L'
docs = myColl.find('name like :param').bind('param','L%').execute()

myDoc = docs.fetch_one()
while myDoc:
  print(myDoc)
  myDoc = docs.fetch_one()

Node.js JavaScript 代码

// Use the collection 'my_collection'
var myColl = db.getCollection('my_collection');

// Find a single document that has a field 'name' that starts with 'L'
myColl
  .find('name like :name')
  .bind('name', 'L%')
  .limit(1)
  .execute(function (doc) {
    console.log(doc);
  })
  .then(function () {
    // handle details
  });

// Get all documents with a field 'name' that starts with 'L'
myColl
  .find('name like :name')
  .bind('name', 'L%')
  .execute(function (doc) {
    console.log(doc);
  })
  .then(function () {
    // handle details
  });

C# 代码

// Use the collection "my_collection"
var myColl = db.GetCollection("my_collection");

// Find a single document that has a field "name" that starts with "L"
var docs = myColl.Find("name like :param")
.Limit(1).Bind("param", "L%").Execute();

Console.WriteLine(docs.FetchOne());

// Get all documents with a field "name" that starts with "L"
docs = myColl.Find("name like :param")
.Bind("param", "L%").Execute();

while (docs.Next())
{
    Console.WriteLine(docs.Current);
}

Python 代码

# Use the collection 'my_collection'
my_coll = my_schema.get_collection('my_collection')

# Find a single document that has a field 'name' that starts with 'L'
docs = my_coll.find('name like :param').limit(1).bind('param', 'L%').execute()

print(docs.fetch_one())

# Get all documents with a field 'name' that starts with 'L'
docs = my_coll.find('name like :param').bind('param', 'L%').execute()

doc = docs.fetch_one()
print(doc)

Java 代码

// Use the collection 'my_collection'
Collection myColl = db.getCollection("my_collection");

// Find a single document that has a field 'name' that starts with 'L'
DocResult docs = myColl.find("name like :name").bind("name", "L%").execute();

System.out.println(docs.fetchOne());

// Get all documents with a field 'name' that starts with 'L'
docs = myColl.find("name like :name").bind("name", "L%").execute();

while (docs.hasNext()) {
    DbDoc myDoc = docs.next();
    System.out.println(myDoc);
}

C++ 代码

// Use the collection 'my_collection'
Collection myColl = db.getCollection("my_collection");

// Find a single document that has a field 'name' that starts with 'L'
DocResult docs = myColl.find("name like :param")
                       .limit(1).bind("param", "L%").execute();

cout << docs.fetchOne() << endl;

// Get all documents with a field 'name' that starts with 'L'
docs = myColl.find("name like :param")
             .bind("param","L%").execute();

DbDoc myDoc;
while ((myDoc = docs.fetchOne()))
{
  cout << myDoc << endl;
}

有关 find() 在 EBNF 中语法的详细信息,请参阅 CollectionFindFunction