Need help about how to write a filter with python client v4

let’s say I have objects as below:
A1{
has_b:[B1,B2 ] # references
}

A2{
has_b:[B3,B4 ] # references
}

B1{
field1:1
field2:2
}

B2{
field1:3
field2:4
}

B3{
field1:1
field2:3
}

B4{
field1:2
field2:4
}

if I use I filter like this on collection A
Filter.by_ref(“has_b”).by_property(“field1”).equal(1) & Filter.by_ref(“has_b”).by_property(“field2”).equal(2)

with current filter I can get both A1 and A1, because the filter find B3 has field1=1 and B4 has field=2 so also find A2 which I don’t want.

I actually want to find only A1 because I want to find the A object which have a B object refernece with field1=1 and field2=2 in the same B object which should only be A1 with B1 reference.

Is this possible? how to write the filter or graphql? Thanks

HI, I just tested this and it works as expected:

import weaviate
from weaviate.collections.classes.config import Property, DataType, ReferenceProperty
from weaviate.collections.classes.filters import Filter

client = weaviate.connect_to_local()
client.collections.delete(["a", "b"])
b = client.collections.create(
    "a",
    properties=[
        Property(name="field1", data_type=DataType.INT),
        Property(name="field2", data_type=DataType.INT),
    ],
)
a = client.collections.create(
    name="b", references=[ReferenceProperty(name="has_b", target_collection=b.name)]
)
b1 = b.data.insert(properties={"field1": 1, "field2": 2})
b2 = b.data.insert(properties={"field1": 3, "field2": 4})
b3 = b.data.insert(properties={"field1": 1, "field2": 3})
b4 = b.data.insert(properties={"field1": 2, "field2": 4})

a1 = a.data.insert({}, references={"has_b": [b1, b2]})
a2 = a.data.insert({}, references={"has_b": [b3, b4]})

objects = a.query.fetch_objects(
    filters=Filter.by_ref("has_b").by_property("field1").equal(1)
    & Filter.by_ref("has_b").by_property("field2").equal(2),
).objects
assert len(objects) == 1
assert objects[0].uuid == a1

(Note that if you do a code-block if you use ``` which makes things easier to read)

1 Like

@Dirk
Thank you for the quick reply.
I will try your code as soon as possible.
I just want to make sure if I understand right.
So filter like this:

filters=Filter.by_ref("has_b").by_property("field1").equal(1)
    & Filter.by_ref("has_b").by_property("field2").equal(2)

means to find the A object has reference of B object with filed1=1 and field2=2 in one B object right?
My actual case is a filter like this but I think nested ref shouldn’t effect this.

Filter.by_ref("belong_to_file_data").by_ref("belong_to_file").by_property("auth_buss_id").equal(file_auth.auth_buss_id)  &
Filter.by_ref("belong_to_file_data").by_ref("belong_to_file").by_property("auth_type").equal(file_auth.auth_type) &
Filter.by_ref("belong_to_file_data").by_ref("belong_to_file").by_property("auth_level").less_or_equal(file_auth.auth_level)

I want to filter by the file object with “auth_buss_id”,“auth_type”,“auth_level” meet condition in the same file.

But I got some result with none of the file can match the all of the three condition at the same time but only partial of it.I will do more test.

I tried your code.
Is there a small mistake in your code?

b = client.collections.create(
    "a",
    properties=[
        Property(name="field1", data_type=DataType.INT),
        Property(name="field2", data_type=DataType.INT),
    ],
)

should it be like this?

b = client.collections.create(
    "b",
    properties=[
        Property(name="field1", data_type=DataType.INT),
        Property(name="field2", data_type=DataType.INT),
    ],
)

your example did work as expect but if I change the filter to like this:

client.collections.delete(["a", "b", ])
b = client.collections.create(
    "b",
    properties=[
        Property(name="field1", data_type=DataType.INT),
        Property(name="field2", data_type=DataType.INT),
    ],
)
a = client.collections.create(
    name="a", references=[ReferenceProperty(name="has_b", target_collection=b.name)]
)

b1 = b.data.insert(properties={"field1": 1, "field2": 2})
b2 = b.data.insert(properties={"field1": 3, "field2": 4})
b3 = b.data.insert(properties={"field1": 1, "field2": 3})
b4 = b.data.insert(properties={"field1": 2, "field2": 4})

a1 = a.data.insert({}, references={"has_b": [b1, b2]})
a2 = a.data.insert({}, references={"has_b": [b3, b4]})

objects = a.query.fetch_objects(
    filters=Filter.by_ref("has_b").by_property("field1").equal(1)
            & Filter.by_ref("has_b").by_property("field2").equal(4),
).objects

print(objects)
print(len(objects))

there should be no b object with field1==1 and field2==4, but the result is like:

[Object(uuid=_WeaviateUUIDInt('795f9ef0-76c6-4e8e-9113-91933f442ddf'), metadata=MetadataReturn(creation_time=None, last_update_time=None, distance=None, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={}, references=None, vector=None, collection='A'), Object(uuid=_WeaviateUUIDInt('864c1bce-5354-4fd3-b7ea-0627f74ae5cb'), metadata=MetadataReturn(creation_time=None, last_update_time=None, distance=None, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={}, references=None, vector=None, collection='A')]
2

That seems to be a bug - I’ll take a look (note I posted this in your other thread by accident first)

please let me know if there is any update.Thanks

I had a look and it seems to be a general problem and not GRPC/client related (so a GQL query gives the same result)

This is outside of my are of expertise and I don’t have time to dig onto that, could you create a bugreport at Issues · weaviate/weaviate · GitHub?

Ok. Thank you.
Just want to make sure this behavior is unexpected , right?
I am not familiar with GQL so I am not sure if this is a bug or expected behavior .

I would lean towards bug/unexpected behaviour.

I mentioned GQL because I used it to test if the client does something wrong or if it is how weaviate handles that query