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

95 Views Asked by At

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" : "[email protected]",
    "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.

1

There are 1 best solutions below

1
René-André On BEST ANSWER

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

  • retrieve the document's field and convert it to a simple list
  • remove the item from the simple list using its index
  • set the document's field as the simple list.

Such as:

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