4.3.2 Collection.find()

find(SearchConditionStr) 函數用於在集合中搜尋文件,類似於 SQL 資料庫的 SELECT 陳述式。它採用搜尋條件字串 (SearchConditionStr) 作為參數,以指定應該從資料庫傳回的文件。execute() 函數觸發 find() 操作的實際執行。

SearchConditionStr 可以採用下列其中一種形式

  • 如果未指定 SearchConditionStrfind() 操作會傳回集合中的所有文件。

    // Get a collection
    var myColl = session.getSchema("world_x").getCollection("countryinfo");
    // To return all documents in world_x: 
    myColl.find().execute();
  • 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 上的元素比較的數值。萬用字元 %_ 可在 value 中與 LIKE 運算子搭配使用,就像在 MySQL WHERE 子句中一樣。例如

      myColl.find("Name LIKE 'Austra%'")
      myColl.find("geography.Continent LIKE 'Asi_'")
    • operator:下列運算子可在 SearchConditionStr 中使用:OR (||)AND (&&)XORISNOTBETWEENINLIKEOVERLAPS!=<>>>=<<=&|<<>>+-*/~%。以下是一些關於使用運算子的範例

      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 路徑指向某些非 Null 元素的所有文件。例如

      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)
      ...

      OVERLAPS 運算子會比較兩個 JSON 片段,如果兩個片段在任何鍵值組或陣列元素中都有任何共通的值,則傳回 true (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() 搭配使用

// 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);
}

另請參閱 CollectionFindFunction,以瞭解 EBNF 中 find() 的語法。