sql >> データベース >  >> NoSQL >> MongoDB

$内または集約式として$regexを使用する方法

    $ expr内のすべて は集計式であり、ドキュメントは「明示的にできないと言う」ことはできません。 、ただし、名前付き演算子の欠如 および JIRA issue SERVER-11947 確かにそう言う。したがって、正規表現が必要な場合は、を使用する以外に選択肢はありません。 $ where 代わりに:

    db.getCollection('permits').find({
      "$where": function() {
        var description = this.inspections
           .sort((a,b) => b.inspectionDate.valueOf() - a.inspectionDate.valueOf())
           .shift().description;
    
         return /^Found a .* at the property$/.test(description) ||
               description === "Health Inspection";
    
      }
    })
    

    $ exprは引き続き使用できます 完全一致の集計式、または $ where とりあえず。ただし、現時点では、MongoDBが理解できる正規表現は $regexのみです。 「クエリ」式 内 。

    実際に「必要」した場合 $where 、現在有効な唯一のアプローチは、最初にアレイとは別にフィールドを「投影」し、次に $ match 通常のクエリ式を使用:

    db.getCollection('permits').aggregate([
      { "$addFields": {
         "lastDescription": {
           "$arrayElemAt": [
             "$inspections.description",
             { "$indexOfArray": [
               "$inspections.inspectionDate",
               { "$max": "$inspections.inspectionDate" }
             ]}
           ]
         }
      }},
      { "$match": {
        "lastDescription": {
          "$in": [/^Found a .* at the property$/,/Health Inspection/]
        }
      }}
    ])
    

    これは、最大の日付値を持つ配列内のアイテムを探しているように見えるという事実につながります。 JavaScript構文は、ここでの正しいアプローチが代わりにであることを明確にする必要があります $ sort 「更新」の配列。このようにして、配列の「最初の」項目を「最新」にすることができます。そして、これは通常のクエリで実行できることです。

    順序を維持するには、 $ push および $ sort このように:

    db.getCollection('permits').updateOne(
      { "_id": _idOfDocument },
      {
        "$push": {
          "inspections": {
            "$each": [{ /* Detail of inspection object */ }],
            "$sort": { "inspectionDate": -1 }
          }
        }
      }
    )
    

    実際、 $ each> updateMany() 既存のすべてのドキュメントを更新します:

    db.getCollection('permits').updateMany(
      { },
      {
        "$push": {
          "inspections": {
            "$each": [],
            "$sort": { "inspectionDate": -1 }
          }
        }
      }
    )
    

    これらは実際に更新中に保存された日付を「変更」する場合にのみ必要であり、これらの更新は bullkWrite() アレイの更新と「ソート」の「両方」を効果的に行うには:

    db.getCollection('permits').bulkWrite([
      { "updateOne": {
        "filter": { "_id": _idOfDocument, "inspections._id": indentifierForArrayElement },
        "update": {
          "$set": { "inspections.$.inspectionDate": new Date() }
        }
      }},
      { "updateOne": {
        "filter": { "_id": _idOfDocument },
        "update": {
          "$push": { "inspections": { "$each": [], "$sort": { "inspectionDate": -1 } } }
        }
      }}
    ])
    

    ただし、実際に日付を「変更」したことがない場合は、単に $ position 修飾子と「追加」の代わりに配列に「事前追加」し、 $ sort

    db.getCollection('permits').updateOne(
      { "_id": _idOfDocument },
      { 
        "$push": { 
          "inspections": {
            "$each": [{ /* Detail of inspection object */ }],
            "$position": 0
          }
        }
      }
    )
    

    配列が永続的に並べ替えられるか、少なくとも「最新の」日付が実際には常に「最初の」エントリになるように作成されている場合は、通常のクエリ式を使用できます。

    db.getCollection('permits').find({
      "inspections.0.description": { 
        "$in": [/^Found a .* at the property$/,/Health Inspection/]
      }
    })
    

    したがって、ここでの教訓は、実際には必要のないロジックに計算式を強制しようとしないことです。アレイのコンテンツを「保存済み」として注文して「最新の日付を最初の」にすることができないという説得力のある理由はありません。 " 、そして他の順序でアレイが必要だと思ったとしても、どちらの使用例がより重要であるかを検討する必要があります。

    正規表現が文字列の先頭に固定されているか、クエリ式の少なくとも他の何かが完全に一致する限り、インデックスをある程度利用することもできます。

    アレイを実際に並べ替えることができないと思われる場合は、 $ where JIRAの問題が解決するまでは、クエリが唯一の選択肢です。これは、現在目標としている4.1リリースで実際に行われることを願っていますが、せいぜい6か月から1年である可能性が高いです。




    1. dockermongoに接続できません

    2. CouchbaseDbaの便利なスクリプト

    3. 複数のフィールドによるMongoDBテキスト検索フィルター

    4. SungoクエリDistinctwithSumが機能していません