MongoDB insert/update/delete elements of an array which is an element to another array

StackOverflow https://stackoverflow.com/questions/21542319

  •  06-10-2022
  •  | 
  •  

質問

Consider the following document:

{
    "entity_id" : 10,
    "features" : 
    [ 
    {
        "10" : "Test System 2"
    }, 
    {
        "20" : "System 2 Description"
    }, 
    {
        "30" : ["Free", "Monthly", "Quaterly"]
    }, 
    {
        "40" : ["Day", "Swing"]
    }
],
}

I need to, in as few statements as possible, to achieve the following:

  1. Given a document like so:

    {"feature_id" : "30", "value" : ["Free"]}
    

    get the corresponding element of the array "features" to contain ["Free"] instead of ["Free", "Monthly", "Quaterly"]

  2. Given a document like so:

    {"feature_id" : "50", "value" : ["Bonds", "Commodities"]}
    

    create a new element of the array "features" looking like

    {"50" : ["Bonds", "Commodities"]}
    
  3. Given a document like so:

    {"feature_id" : "40", "value" : ""} 
    

remove the corresponding element from the array "features".

役に立ちましたか?

解決

Data model

Your data model isn't easy to work with given your desired updates.

If you want to use an array, I would suggest changing the document structure to look like:

{
    "entity_id" : 10,
    "features" : [
        {
            feature_id: "10",
            value : "Test System 2"
        },
        {
            feature_id: "20",
            value: "System 2 Description"
        }, 
        {
            feature_id: "30",
            value: ["Free", "Monthly", "Quaterly"]
        }, 
        {
            feature_id: "40",
            value: ["Day", "Swing"]
        }
    ],
}

Alternatively, you could model as an embedded document:

{
    "entity_id" : 10,
    "features" : {
        "10" : "Test System 2",
        "20" : "System 2 Description",
        "30" : ["Free", "Monthly", "Quaterly"],
        "40" : ["Day", "Swing"]
    }
}

The benefit of modeling as an array is that you can add a multikey index across all features/values.

If you model as an embedded document, you could reference fields directly (i.e. features.10). This assumes you know what the keys are going to be, and you would have to index each feature value separately.

I'll assume the first format for the examples below. Also note that your key values have to match in type (so string "10" will not match number 10).

Example 1

Given a document like so:

{"feature_id" : "30", "value" : ["Free"]} get the corresponding element of the array "features" to contain ["Free"] instead of ["Free", "Monthly", "Quaterly"]

Sample update:

db.docs.update(
    // Criteria (assumes entity_id is unique)
    {
        entity_id: 10,
        features: {
            // Using $elemMatch to find feature_id with string "30"
            $elemMatch: { feature_id: "30" },
        }
    },

    // Update
    { $set: {
        "features.$.value" : ["Free"]
    }}
)

Example 2

Given a document like so:

{"feature_id" : "50", "value" : ["Bonds", "Commodities"]} create a new element of the array "features" looking like

{"50" : ["Bonds", "Commodities"]}

Sample update:

db.docs.update(
    // Criteria (assumes entity_id is unique)
    {
        entity_id: 10,
    },

    // Update
    { $push: {
        "features" : { "feature_id" : "50", value: ["Bonds", "Commodities"] }
    }}
)

Example 3

Given a document like so:

{"feature_id" : "40", "value" : ""}

remove the corresponding element from the array "features".

Sample update:

db.docs.update(
    // Criteria (assumes entity_id is unique)
    {
        entity_id: 10,
    },

    // Update
    { $pull: {
        "features" : { "feature_id" : "40" }
    }}
)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top