Michael Paccione
Michael Paccione

Reputation: 2817

SQLAlchemy - How to filter_by multiple dynamic OR values?

I have a pretty reasonable use case: Multiple possible filter_by matches for a single column. Basically, a multiselect JS dropdown on front end posts multiple company industries to the backend. I need to know how to write the SQLAlchemy query and am surprised at how I couldn't find it.

{ filters: { type: "Industry", minmax: false, value: ["Financial Services", "Biotechnology"] } }
@app.route("/dev/api/saved/symbols", methods=["POST"])
@cross_origin(origin="*")
def get_saved_symbols():
    req = request.get_json()
    # res = None
    # if "minmax" in req["filters"]:
    #     idx = req["filters"].index("minmax")
    #     if req["filters"][idx] == "min":
    #         res = db.session.query.filter(Company[req["filter"]["type"]] >= req["filters"]["value"])
    #     else:
    #         res = db.session.query.filter(Company[req["filter"]["type"]] <= req["filters"]["value"])

    # else:
    res = db.session.query.filter_by(Company[req["filters"]["type"]] == req["filters"]["value"])

    return jsonify(res)

As you can see I am also working on a minmax which is like an above or below filter for other columns like price or market cap. However, the multiselect OR dynamic statement is really what I am stuck on...

Upvotes: 0

Views: 4293

Answers (1)

Michael Paccione
Michael Paccione

Reputation: 2817

I ended up creating a separate filter function for this that I can than loop over results with.

I will just show the first case for brevity. I am sending a list of strings in which I create a list of filters and then use the or_ operator imported from sqlalchemy package.

def company_filter(db, filter_type, filter_value, minmax):
    match filter_type:
        case "industry":
            filter_list = []

            for filter in filter_value:
                filter_list.append(Company.industry == filter)

            return db.query(Company).with_entities(Company.id, Company.symbol, Company.name, Company.monthly_exp).filter(or_(*filter_list))
        ...

Upvotes: 2

Related Questions