SODA for In-Database JavaScriptによるコレクション内のドキュメントの検索

コレクション内のドキュメントを検索するには、SodaCollection.find()を呼び出します。SodaOperationオブジェクトが作成されて戻されます。これは、非ターミナル・メソッドおよびターミナル・メソッドを含むメソッド・チェーンを介して使用されます。

問合せを実行するには、SodaOperation.getCursor()を呼び出して、その結果のカーソルを取得します。次に、カーソルを使用して結果リスト内の各ドキュメントにアクセスします。これは、例8-1およびその他の例で示されています。リソースを節約するために、カーソルを必ずクローズすることが重要です。

ただし、これはコレクション内のドキュメントを検索する際の一般的なワークフローではありません。SodaOperationクラスで提供される複数のメソッドをつなげる方が一般的です。

例8-9 キーによるドキュメントの検索

この例は、メソッドfind()key()およびgetOne()を使用してドキュメントをキーで検索する方法を示しています。

export function findDocByKey(searchKey){

  const collectionName = 'MyCollection';

  // open the collection in preparation of a document lookup
  const col = soda.openCollection(collectionName);
  if (col === null){
    throw new Error(`${collectionName} does not exist`);
  }

  try{
    // perform a lookup of a document with the key provided as a 
    // parameter to this function. Keys are like primary keys,
    // the lookup therefore can only return 1 document max
    const doc = col.find()
                   .key(searchKey)
                   .getOne();
    console.log(`
      document found for key ${searchKey}
      contents: ${doc.getContentAsString()}`
    );
  } catch(err){
      throw new Error(
        `error retrieving document with key ${searchKey} (${err})`
      );
  }
}

ノート:

キーは、数値形式の場合でも引用符で囲む必要があります。

指定されたキーの検索に失敗した場合、データベースはORA-01403 (「データが見つかりません。」)例外をスローします。例外は適切に処理することをお薦めします。この例では、エラーが確実に検出され、業界で最もよく知られている方法に従って処理される責任をファンクションのコール元が担っています。

例8-10 複数のキーを使用したドキュメントの検索

この例では、メソッドfind()keys()getCursor()およびgetNext()を使用して、配列で指定された複数のキーを検索します。

この例で使用されているemployeesCollectionの作成方法の詳細は、例8-8を参照してください。

export function findDocByKeys(searchKeys){
  
  if(!Array.isArray(searchKeys)){
    throw new Error('please provide an array of search keys');
  }

  // open a collection in preparation of a document lookup
  const col = soda.openCollection('employeesCollection');
  if (col === null){
    throw new Error('employeesCollection does not exist');
  }

  try{
    // perform a lookup of a set of documents using
    // the "keys" array provided
    const docCursor =
      col.find()
         .keys(searchKeys)
         .getCursor();

    let doc
      while((doc = docCursor.getNext())){
        console.log(`
          document found for key ${doc.key}
          contents: ${doc.getContentAsString()}`
        );
      }
      docCursor.close();
  } catch(err){
      // there is no error thrown if one/all of the keys aren't found
      // this error handler is generic
      throw new Error(
        `error retrieving documents with keys ${searchKeys} (${err})`
      );
  }
}

find()操作は、エラーで失敗するのではなく、単に、コレクションで見つからないキーのデータを返しません。キーが見つからない場合は、何も戻されません。

例8-11 QBEを使用したコレクション内のドキュメントのフィルタリング

この例では、filter()を使用してコレクション内のドキュメントを検索します。非ターミナルのSodaOperation.filter()メソッドは、コレクション内のJSONドキュメントをフィルタする強力な方法を提供し、複雑なドキュメント問合せおよびJSONドキュメントの順序付けを可能にします。フィルタ仕様には、比較、正規表現、論理演算子および空間演算子などを含めることができます。

filterConditionで定義されている検索式は、部門30で働く110より大きい従業員IDを持つすべての従業員に一致します。

この例で使用されているemployeesCollectionの作成方法の詳細は、例8-8を参照してください。

export function findDocByFiltering(){

  // open a collection in preparation of a document
  // lookup. This particular collection contains all the
  // rows from the HR.employees table converted to SODA
  // documents.
  const col = soda.openCollection('employeesCollection');
  if(col === null){
    throw new Error(`employeesCollection does not exist`);
  }

  // find all employees with an employee_id > 100 and
  // last name beginning with M
  const filterCondition = {
    "$and": [
      { "lastName": { "$upper": { "$startsWith": "M" } } },
      { "_id": { "$gt": 100 } }
    ]  
  };

  try{
    
    // perform the lookup operation using the QBE defined earlier
    const docCursor = col.find()
                         .filter(filterCondition)
                         .getCursor();
    let doc;
    while ((doc = docCursor.getNext())){
      console.log(`
        ------------------------------------
        document found matching the search criteria
        - key:           ${doc.key}
        - _id:           ${doc.getContent()._id}
        - name:          ${doc.getContent().lastName}`
      );
    }

    docCursor.close();
  } catch(err){
      throw new Error(`error looking up documents using a QBE: ${err}`);
  }
}

関連項目:

例8-12 ページ区切り問合せでのskip()およびlimit()の使用

行数が過度に大きくなる場合は、ページ分けするか、戻されるドキュメントの数を制限できます。この例では、このような状況でskip()およびlimit()を使用する方法を示します。

この例で使用されているemployeesCollectionの作成方法の詳細は、例8-8を参照してください。

export function paginationExample(){

  // open a collection in preparation of a document
  // lookup. This particular collection contains all the
  // rows from the HR.employees table converted to SODA
  // documents.
  const col = soda.openCollection('employeesCollection');
  if(col === null){
    throw new Error ('employeesCollection does not exist, aborting');
  }

  // find all employees with an employee_id > 100 and
  // last name beginning with E
  const filterCondition = {
    "$and": [
      { "lastName": { "$upper": { "$startsWith": "M" } } },
      { "_id": { "$gt": 100 } }
    ]
  };

  try{

    // perform the lookup operation using the QBE, skipping the first
    // 5 documents and limiting the result set to 10 documents
    const docCursor = 
      col.find()
         .filter(filterCondition)
         .skip(5)
         .limit(10)
         .getCursor();
    let doc;
    while ((doc = docCursor.getNext())){
      console.log(`
        ------------------------------------
        document found matching the search criteria
        - key:           ${doc.key}
        - employee id:   ${doc.getContent().employeeId}`
      );
    }

    docCursor.close();
  } catch(err){
      throw new Error(
        `error looking up documents by QBE (${err})`
      );
  }
}

例8-13 ドキュメント・バージョンの指定

この例では、非ターミナル・メソッドversion()を使用して、特定のドキュメント・バージョンを指定します。これは、書込み操作用のターミナル・メソッドとともに使用する場合、オプティミスティック・ロックの実装に便利です。

この例で使用されているemployeesCollectionの作成方法の詳細は、例8-8を参照してください。

export function versioningExample(searchKey, version){

  // open a collection in preparation of a document
  // lookup. This particular collection contains all the
  // rows from the HR.employees table converted to SODA
  // documents.
  const col = soda.openCollection("employeesCollection");

  try{
    // perform a lookup of a document using the provided key and version
    const doc = col
      .find()
      .key(searchKey)
      .version(version)
      .getOne();
    console.log(`
      document found for key ${doc.key}
      contents: ${doc.getContentAsString()}`
    );
  } catch(err){
      throw new Error(
        `${err} during lookup. Key: ${searchKey}, version: ${version}`
      );
  }
}

SODAでキーとバージョン・タグに一致するドキュメントが見つからない場合は、ORA-01403: データが見つかりません。エラーがスローされます。

例8-14 見つかったドキュメントの数のカウント

この例では、find()filter()およびcount()メソッドを使用して、コレクションで見つかったドキュメントの数をカウントする方法を示します。filter()式は、部門30で働くすべての従業員に結果を制限します。

この例で使用されているemployeesCollectionの作成方法の詳細は、例8-8を参照してください。

export function countingExample(){

  // open a collection in preparation of a document
  // lookup. This particular collection contains all the
  // rows from the HR.employees table converted to SODA
  // documents.
  const col = soda.openCollection("employeesCollection");
  if(col === null){
    throw new Error('employeesCollection does not exist');
  }

  try{

    // perform a lookup operation identifying all employees working
    // in department 30, limiting the result to headers only
    const filterCondition = {"departmentId": 30};
    const numDocs = col.find()
                       .filter(filterCondition)
                       .count();
    console.log(`there are ${numDocs} documents matching the filter`);
  } catch(err){
      throw new Error(
        `No document found in 'employeesCollection' matching the filter`
      );
  }
}