0

次のような「受取人」BsonDocumentがあります。

{
  "Token" : "0b21ae960f25c6357286ce6c206bdef2",
  "LastAccessed" : ISODate("2012-07-11T02:14:59.94Z"),
  "Firstname" : "John",
  "Lastname" : "Smith",
  "PayrollInfo" : [{
      "Tag" : "EARNINGS",
      "Value" : "744.11",
    }, {
      "Tag" : "DEDUCTIONS",
      "Value" : "70.01",
    }],
  },
  "Status" : "1",
  "_id" : ObjectId("4fc263158db2b88f762f1aa5")
}

Payee _id に基づいてこのドキュメントを取得します。

var collection = database.GetCollection("Payee");
var query = Query.EQ("_id", _id);
var bDoc = collection.FindOne(query);

次に、PayrollInfo 配列内の特定のオブジェクトを更新する必要がある場合があります。そのため、配列内で適切な「タグ」を持つオブジェクトを検索し、「値」をデータベースに更新します。これを行うには、次のロジックを使用します。

var bsonPayrollInfo = bDoc["PayrollInfo", null];
if (bsonPayrollInfo != null)
{
    var ArrayOfPayrollInfoObjects = bsonPayrollInfo.AsBsonArray;
    for (int i = 0; i < ArrayOfPayrollInfoObjects.Count; i++)
    {
        var bInnerDoc = ArrayOfPayrollInfoObjects[i].AsBsonDocument;
        if (bInnerDoc != null)
        {
            if (bInnerDoc["Tag"] == "EARNINGS")
            {
                //update here
                var update = Update
                    .Set("PayrollInfo."+ i.ToString() + ".Value", 744.11)
                collection.FindAndModify(query, null, update);
                bUpdateData = true;
                break;
            }
        }
    }
}

if (!bUpdateData)
{
    //Use Update.Push.  This works fine and is not relevant to the question.
}

このコードはすべて正常に動作しますが、結果を得るのが面倒だと思います。これを行うより簡潔な方法はありますか?基本的に、BsonDocument の配列内のオブジェクトを更新するより良い方法を見つけようとしています。

4

2 に答える 2

1

それがあなたを助ける場合に備えて、ここに私の答えを入れてください。@MrKurtの回答(ありがとうございます!)に基づいて、コードを作り直すために私が行ったことは次のとおりです。

var collection = database.GetCollection("Payee");
var query = Query.EQ("_id", _id);

if (collection.Count(query) > 0)
{
    //Found the Payee.  Let's save his/her Tag for EARNINGS
    UpdateBuilder update = null;

    //Check if this Payee already has any EARNINGS Info saved.
    //If so, we need to update that.
    query = Query.And(query,
        Query.EQ("PayrollInfo.Tag", "EARNINGS"));

    //Update will be written based on whether we find the Tag:EARNINGS element in the PayrollInfo array
    if (collection.Count(query) > 0)
    {
        //There is already an element in the PayrollInfo for EARNINGS
        //Just update that element
        update = Update
            .Set("PayrollInfo.$.Value", "744.11");
    }
    else
    {
        //This user does not have any prior EARNINGS data.  Add it to the user record
        query = Query.EQ("_id", _id);
        //Add a new element in the Array for PayrollInfo to store the EARNINGS data
        update = Update.Push("PayrollInfo",
                    new BsonDocument {{"Tag", "EARNINGS"}, {"Value", "744.11"}}
                 ); 
    }

    //Run the update
    collection.FindAndModify(query, null, update);
}

元のコードよりも見た目は悪くありませんが、はるかに直感的で、位置演算子について多くのことを学ぶことができました。

于 2012-07-20T22:00:50.923 に答える
1

Mongo には、配列内の一致した値を操作できる位置演算子があります。構文は次のとおりです。field1.$.field2

Mongo シェルからの使用方法の例を次に示します。

db.dots.insert({tags: [{name: "beer", count: 2}, {name: "nuts", count: 3}]})
db.dots.update({"tags.name": "beer"}, {$inc: {"tags.$.count" : 1}})
result = db.dots.findOne()
{ "_id" : ObjectId("50078284ea80325278ff0c63"), "tags" : [ { "name" : "beer", "count" : 3 }, { "name" : "nuts", "count" : 3 } ] }
于 2012-07-19T03:46:59.880 に答える