0

I am building a REST Api on Flask + MongoDB for a HR website. I need to filter search results by programming language, experience, city etc.

I also have a filter 'framework'. But I also need to implement an additional framework filter which is "nice to have, but not necessary" I just need to sort the items order including the additional framework.

The framework itself is listed in the 'about' field as a string, so I am using a regex to find it.

For example, I am looking for a Python developer who must have a Flask knowledge, but it is nice to know React too. So I need to have a search result like this:

  1. Dev A: Python, Flask, React
  2. Dev B: Python, Flask, React
  3. Def C: Python, Flask

The problem is that this second framework is not mandatory, when the first is so I can't query with '$or' or '$in'. The only option I see is that I query for the first framework and then sort it by presence of the second framework.

Is there a way to implement it in MongoDB?

1 Answer 1

1

OK, so after doing some research I was able to find a solution:

def _filter_by_additional_framework(collection, query):
    results = collection.aggregate([
        {'$limit': 1},
        {'$lookup':
            {
                'from': 'profiles',
                'pipeline': [
                    {'$match': {
                        '$text': {
                            '$search': f"\"{query['framework']}\" \"{query['framework2']}\""}}
                    },
                    {'$sort': {'Rating': DESCENDING}}
                ], 'as': 'col1'}},
        {'$lookup':
            {
                'from': 'profiles',
                'pipeline': [
                    {'$match': {
                        '$text': {
                            '$search': f"\"{query['framework']}\" -\"{query['framework2']}\""}}
                    },
                    {'$sort': {'Rating': DESCENDING}}
                ], 'as': 'col2'}},
        {'$project': {'union': {'$concatArrays': ["$col1", "$col2"]}}},
        {'$unwind': '$union'},
        {'$replaceRoot': {'newRoot': '$union'}},
        {'$project': search_result_order()},
    ], collation=Collation(locale="en_US", numericOrdering=True))

    return results

It performs 2 lookups by the same field in a collection (first one looking for say Flask AND React ('"Flask" "React"') and the second one Flask AND NOT React ('"Flask" -"React"'). I also had to add text indexes to some fields to perform a text lookup.

Also, you may notice that there is a $sort expression in each pipeline. This is for additional sort (Rating in my case). And the second argument (collation) in aggregate is for sorting a string field by integer. So as a result you can sort every query as you would like to separately or you can move your sort expression out of the pipeline and sort the whole query combined.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.