简体   繁体   中英

Mongodb Pymongo using $set to create an array/list/collection

I'm trying to use $set to create an array/list/collection (not sure which is proper terminology), and I'm not sure how to do it. For example:

I have a document inserted into my database that looks like this:

"_id": (unique, auto-generated id)
"Grade": Sophomore

I want to insert a collection/list/array using update. So, basically I want this:

"_id": (unique, auto-generated id)
"Grade": Sophomore
"Information"{
           "Class_Info": [
                        {"Class_Name": "Math"}
                         ]

What I've been doing so far is using.update and dot notation. So, what I was trying to do was use $set like this:

collection.update({'_id': unique ID}, {'$set': {'Information.Class_Info.Class_Name': 'Math}})

However, what that is doing is making Class_Info a document and not a list/collection/array, so it's doing:

"_id": (unique id)
"Grade": Sophomore
"Information"{
           "Class_Info": {
                        "Class_Name": "Math"
                         }

How do I specify that I want Class_Info to be a list? IF for some reason I absolutely cannot use $set to do this, it is very important that I can use dot notation because of the way the rest of my program works, so if I'm supposed to use something other than $set, can it have dot notation to specify where to insert the list? (I know $push is another option, but it doesn't use dot notation, so I can't really use it in my case).

Thanks!

If you want to do it with only one instruction but starting up from NOT having any key created yet, this is the only way to do it ($set will never create an array that's not explicit, like { $set : { somekey : [] } }

db.test.update({_id:(unique id)}, 
{$push: {"Information.Class_Info": { "Class_Name":"Math" }}})

This query does the trick, push to a non-existing key (Information.Class_Info) the object you need to create as an array. This is the only possible solution with only one instruction, using dot notation and that works.

There is a way to do it with one instructions, $set and dot notation, as follows:

db.test.updateOne(
  { _id: "my-unique-id" },
  { $set: { 
    "Information.Class_Info": [ { "Class_Name": "Math" } ] 
  }}
)

There is also a way to do it with two instructions and the array index in the dot notation, allowing you to use similar statements to add more array elements:

db.test.updateOne(
  { _id: "my-unique-id" },
  { $set: { "Information.Class_Info": [] }}
)
db.test.updateOne(
  { _id: "my-unique-id" },
  { $set: { 
    "Information.Class_Info.0": { "Class_Name": "Math" },
    "Information.Class_Info.1": { "Class_AltName": "Mathematics" } 
  }}
)

Deviating from these options has interesting failure modes:

  • If you try to combine the second option into a single updateOne() call, which is usually possible, MongoDB will complain that "Updating the path 'Information.Class_Info.0' would create a conflict at 'Information.Class_Info'"

  • If you try to use dot the notation with the array index ( "Information.Class_Info.0.Class_Name": "Math" ) but without creating an empty array first, then MongoDB will create an object with numeric keys ( "0" , "1" , …). It really refuses to create array except when told explicitly using […] (as also told in the answer by @Maximiliano ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM