how to store & update matching values based on $OR operator, in mongodb?

走远了吗. 提交于 2019-12-11 17:18:36

问题


My collections contain nested document and I'm trying to get "Text" present in any of the nested fields such as:

var rerun = { $or: [
                               {"code_exception.java_40.code.Text": { $exists : true, $ne : "" } },//13816
                               {"code_exception.java_15.code.Text":{ $exists : true, $ne : ""} },//13485
                               {"code_exception.java_10.code.Text":{ $exists : true, $ne : ""} },//12994
                               {"code_exception.java_2.code.Text": { $exists : true, $ne : ""} },//13294
                               {"code_exception.java_4.code.Text": { $exists : true, $ne : ""} },//13437
                               {"code_exception.java.code.Text":   { $exists : true, $ne : ""} },//13192
                               {"code_exception.java_1.code.Text": { $exists : true, $ne : ""} }//12951
                              ]}
db.collection.find(rerun).count()//14093

I am able to get the documents which has some "Text" field present it as shown above

Now, I want to store "Text" for each processed document and update another field "Name" with it in that document. I've a hard time getting this logic written in query.

Failed Attempt:

db.collection.find(rerun).forEach(function(document) {
    db.collection.update(
        { "_id": document._id }, 
        { "$set": { "Name": document.code_exception.java_*.code.Text } }
    );
})

* is to substitute with a number [40,15,10,2,4,1, ]. I know this won't work, but can anyone suggest a way obtaining the matched value for "Text" among the $ORs?

For example

  • doc1 in collection if matched with "code_exception.java_15.code.Text":{ $exists : true, $ne : ""} criteria, so it's able to store "code_exception.java_15.code.Text" on the fly and update in "Name" filed for the same doc1.
  • Similarly, doc2 in collection if matched with "code_exception.java.code.Text":{ $exists : true, $ne : ""} criteria, so it's able to store "code_exception.java.code.Text" on the fly and update in "Name" filed for the same doc1.

Got a simple hack!

Since I need to update a field name in the collection if I am able to find Text corresponding to code_exception.java_*.code.Text, where * could be a number [40,15,10,2,4,1, ] which make above fields.

The solution would be to run each filter separately and update Name field. There would be redundant updates for sure, but that won't be a problem since, if some docs are missed by java_40.code, it could be filled by java_1.code or other filters.

My hack using pymongo client:

import pymongo
uri= "<URI>>"
client = pymongo.MongoClient(uri)
filter = { "$and": [
                   {"code_exception.java_1.code.Text": { "$exists" : True, "$ne" : "" } },
                   # {"code_exception.java_15.code.Text":{ $exists : true, $ne : ""} },
                   # {"code_exception.java_10.code.Text":{ $exists : true, $ne : ""} },
                   # {"code_exception.java_2.code.Text": { $exists : true, $ne : ""} },
                   # {"code_exception.java_4.code.Text": { $exists : true, $ne : ""} },
                   # {"code_exception.java.code.Text":   { $exists : true, $ne : ""} },
                   # {"code_exception.java_1.code.Text": { $exists : true, $ne : ""} }
]}

docs = client["<db_name>"]["<coll_name>"].find(filter, no_cursor_timeout=True).batch_size(25)
collection = client["<db_name>"]["<coll_name>"]

def update_coll():

    line_count = 0
    for doc in docs:
        line_count += 1
        getText = doc["code_exception"]["java_1"]["code"]["Text"]
        collection.find_one_and_update({"_id": doc['_id']}, {"$set": {"Name": getText}})
    print(line_count)

if __name__ == '__main__':
    update_coll()

Will execute above code 7 times once for each filter and update Name field!

Does anyone have a better solution?

来源:https://stackoverflow.com/questions/58831053/how-to-store-update-matching-values-based-on-or-operator-in-mongodb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!