barseghyanartur / graphene-elastic

Graphene Elasticsearch/OpenSearch (DSL) integration
https://pypi.org/project/graphene-elastic/
71 stars 18 forks source link

Added nested search in search filter backend #60

Closed lingfromSh closed 3 years ago

lingfromSh commented 3 years ago

Added nested search support.

{
  allPostDocuments(search: {comments: {query:"Python", tag:{value: "MongoDB"}}}) {
    edges {
      node {
        id
        comments {
          author{
            age
            name
          }
          tag
          content
          createdAt
        }
      }
    }
  }
}

The final query will be this. I just combine input with configured, so there will be some duplicated query.

{
  "query": {
    "bool": {
      "should": [
        {
          "nested": {
            "path": "comments.author",
            "query": {
              "match": {
                "comments.author.name.raw": { "query": "Python", "boost": 2 }
              }
            }
          }
        },
        {
          "nested": {
            "path": "comments",
            "query": {
              "bool": {
                "should": [
                  { "match": { "comments.tag": { "query": "MongoDB" } } },
                  {
                    "match": {
                      "comments.content.raw": { "query": "Python", "boost": 3 }
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "nested": {
            "path": "comments",
            "query": { "match": { "comments.tag": { "query": "MongoDB" } } }
          }
        }
      ]
    }
  }
}

Some problems:

  1. Each InputObjectType needs a unique name. I just put a auto-incremented number at the end of their names.
barseghyanartur commented 3 years ago

@lingfromSh:

Awesome, thanks! I'll prepare a release soon.

barseghyanartur commented 3 years ago

@lingfromSh:

Sorry, this broke quite a few things. The following query used to work fine before. Now it does not. Could you fix that?

        query {
          allReadOnlyPostDocuments(search:{content:{value:"Alice"}}) {
            edges {
              node {
                category
                title
              }
            }
          }
        }

Additionally, this creates a backwards compatibility issue. The following query used to work before. Now it does not, unless you replace author with author{age, name}:

{
  allPostDocuments {
    edges {
      node {
        id
        comments {
          author
          tag
          content
          createdAt
        }
      }
    }
  }
}
lingfromSh commented 3 years ago

I figured out the reason why tests failed.


class BaseBackend:

    def __init__(self, args=None):
        self.args = args or {}

class BackendA(BaseBackend):
    ...

class BackendB(BaseBackend):
    ...

if __name__ == "__main__":

    data = {
        "key1": "value1",
        "key2": {
            "nested_key1": {},
            "nested_key2": "nested_value2"
        }
    }

    backend_a = BackendA(args=dict(data))
    backend_b = BackendB(args=dict(data))

    backend_a.args.update(key1="changed")   
    print(backend_b.args)   # {'key1': 'value1', 'key2': {'nested_key1': {}, 'nested_key2': 'nested_value2'}}

    backend_a.args['key2'].update(nested_key1="changed")
    print(backend_b.args)   # {'key1': 'value1', 'key2': {'nested_key1': 'changed', 'nested_key2': 'nested_value2'}}

    print(backend_a.args["key2"] is backend_b.args['key2'])  # True

When CompoundSearchFilterBackend and SearchFilterBackend both did pop operation on the same dict, the tests failed.