pythonmongodbmongodb-querymongoengineflask-mongoengine

In mongoengine how do you target a specific index in a list?


In mongoengine there are pull and unset commands. These allow you to remove values from a list if you provide them with a value to match against or the entire list. While that works without an issue what if I wanted to remove a value from a list in my database by the index value (or if that can't be done, by the field name)? My current problem involves trying to remove a value from 3 different lists (Schedule, SchedulePlainText, ScheduleGrades), which each have 3 different values. I want to target the values as determined by a user inputting an integer (via wtforms).

example document:

{
    "_id" : ObjectId("6376b19ef448207c0a72124b"),
    "FirstName" : "Euphemia",
    "LastName" : "Pickerin",
    "Birthday" : "1978-09-21",
    "Email" : "EPickerin@clearwater.edu",
    "Password" : "pbkdf2:sha256:260000$OkQmjvFCrAhbGEfi$f795ee99c2ea3c9aeb6b823d58c62821010a0d87223ff5fdc22943883a7bf838",
    "AccountType" : "Undergraduate",
    "Address" : "40 Service Drive",
    "LoginCounter" : 0,
    "PartorFullTime" : "Full Time",
    "CreditsEarned" : 92,
    "Advisor" : ObjectId("637e9734a0063d4732ff2cf4"),
    "PhoneNumber" : "309-353-0865",
    "Holds" : "None",
    "Schedule" : [
        ObjectId("637545927a45e617da1cbda5"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("6375458e7a45e617da1cacf3"),
        ObjectId("637545927a45e617da1cbb86")
    ],
    "ScheduleGrades" : [
        "C",
        "C",
        "A",
        "A"
    ],
    "TranscriptGrades" : [
        "A",
        "B",
        "C",
        "A",
        "C",
        "A",
        "C",
        "B",
        "C",
        "A",
        "B",
        "A",
        "B",
        "B",
        "C",
        "A",
        "C",
        "A",
        "B"
    ],
    "Transcript" : [
        ObjectId("6375458e7a45e617da1cacf8"),
        ObjectId("6375458e7a45e617da1cacf8"),
        ObjectId("6375458e7a45e617da1cabeb"),
        ObjectId("6375458e7a45e617da1cabeb"),
        ObjectId("637545927a45e617da1cbc98"),
        ObjectId("6375458e7a45e617da1cacf8"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("6375458e7a45e617da1cae05"),
        ObjectId("6375458e7a45e617da1cae05"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("637545927a45e617da1cbb8b"),
        ObjectId("637545927a45e617da1cbc98"),
        ObjectId("6375458e7a45e617da1cae05"),
        ObjectId("6375458e7a45e617da1cacf8"),
        ObjectId("6375458e7a45e617da1cacf3"),
        ObjectId("6375458e7a45e617da1cabe6")
    ],
    "Major" : ObjectId("639d413260af0c7b888c6fe5"),
    "Minor" : ObjectId("639d408e60af0c7b888c6fda"),
    "SchedulePlainText" : [
        "Vertebrate Physiology",
        "Inorganic Chemistry",
        "Graphic Design I",
        "3-D Digital Design"
    ],
    "TranscriptPlainText" : [
        "Precalculus",
        "Principles of Chemistry I",
        "Principles of Chemistry Lab I",
        "Scientific Programming in Python",
        "Calculus and Analytic Geometry I",
        "Principles of Chemistry II",
        "Principles of Chemistry Lab II",
        "Computer Programming I",
        "Calculus and Analytic Geometry II",
        "Biochemistry for Life Sciences",
        "Organic Chemistry I",
        "Organic Chemistry Lab I",
        "Organic Chemistry II",
        "Organic Chemistry Lab II",
        "Analytical Chemistry",
        "Physical Chemistry I",
        "Physical Chemistry II",
        "Basic Design",
        "Drawing"
    ],
    "ClassCount" : 4
}

my latest attempt to solve the problem:

class removeViaSlotForm(FlaskForm):
    slotid = IntegerField("slot id", validators = [InputRequired()])
    studentid = StringField("Student id", validators = [InputRequired()])


form6 = removeViaSlotForm(request.form)

    if request.method == "POST":
        if "form6" in request.form and form6.validate_on_submit():
            user = allUser.objects(id = form6.studentid.data)
            query1 = { f"unset__Schedule": f"{form6.slotid.data}" }
            query2 = { f"unset__SchedulePlainText": f"{form6.slotid.data}" }
            query3 = { f"unset__ScheduleGrades": f"{form6.slotid.data}" }

            user.update(**query1)
            user.update(**query2)
            user.update(**query3)

            return render_template("/response/useredited.html")

This code works (on a technical level) but it removes all of the values in the list as opposed to targeting just one. Changing unset to pull seemingly does nothing, presumably because it can't find the string "0" (in the case of the user inputting 0 in wtforms).

Anything to push me in the right direction is appreciated.


Solution

  • For each of the 3 fields (Schedule, SchedulePlainText and ScheduleGrades):

    Such as:

    schedule = list(user.Schedule)
    del schedule[form6.slotid.data]
    user.Schedule = schedule
    user.save()