2

I have a Mongo database with lots of documents. All of the documents have a field called "source" which contains the origin name for the document. But a lot of old documents have this field containing "null" (because I hadn't have source by that time) string value. I want to select all those documents and fix this problem by replacing their "source = "null"" values by new values parsed from another fields of the aforementioned documents. Here's what I'm doing to fix the this:

public void FixAllSources() {
    Task.Run(async ()=> {  

        var filter = Builders<BsonDocument>.Filter.And(new List<FilterDefinition<BsonDocument>>() {
            Builders<BsonDocument>.Filter.Exists("url"),
            Builders<BsonDocument>.Filter.Ne("url", BsonNull.Value), 
            Builders<BsonDocument>.Filter.Eq("source", "null")
        });

        var result = await m_NewsCollection.FindAsync(filter);
        var list = result.ToList();

        list.ForEach(bson => {
            bson["source"] = Utils.ConvertUrlToSource(bson["url"].AsString);
        });

    });
}

as you can see, I'm fetching all those documents and replacing their source field by a new value. So now I've got a List of correct BsonDocuments which I need to put back into the database. Unfortunately, I'm stuck on this. The problem is that all of the "Update" methods require filters and I have no idea what filters should I pass there. I just need to put back all those updated documents, and that's it. I'd appreciate any help :)

p.s. I've came up with an ugly solution like this:

list.ForEach(bson => {
    bson["source"] = Utils.ConvertUrlToSource(bson["url"].AsString);
    try {
        m_NewsCollection.UpdateOne( new BsonDocument("unixtime", bson["unixtime"]), new BsonDocument {{"$set", bson}},
            new UpdateOptions {IsUpsert = true});
    }
    catch (Exception e) {
        WriteLine(e.StackTrace);
    }
});

It works for now. But I'd still like to know the better one in case I need to do something like this again. So I'm not putting my own solution as an answer

Konstantin
  • 1,150
  • 13
  • 31
  • Don't load the documents, just set the field on database level. See mongo update command: https://stackoverflow.com/questions/42507640 – Robert Sep 09 '18 at 13:46
  • Sorry, I don't understand how can I do that. Let's make it a bit clearer. In a very simple scenario I want to find a document with source == "null" and set its "source" field to its own "url" field. Where do I get a link to the found document to retrieve its url and set the url's value to the source field, given that each document needs a unique value of this field? – Konstantin Sep 09 '18 at 14:00

0 Answers0