Conditional filters
Overview
Conditional filters may be added to queries such as Object-level
and Aggregate
queries, as well as batch deletion. The operator used for filtering is also called a where
filter.
A filter may consist of one or more conditions, which are combined using the And
or Or
operators. Each condition consists of a property path, an operator, and a value.
Single operand (condition)
Each set of algebraic conditions is called an "operand". For each operand, the required properties are:
- The operator type,
- The property path, and
- The value as well as the value type.
For example, this filter will only allow objects from the class Article
with a wordCount
that is GreaterThan
than 1000
.
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
collection = client.collections.get("Article")
response = collection.query.fetch_objects(
filters=Filter.by_property("wordCount").greater_than(1000),
limit=5
)
for o in response.objects:
print(o.properties) # Inspect returned objects
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"path": ["wordCount"],
"operator": "GreaterThan",
"valueInt": 1000
}
query_result = (
client.query
.get("Article", "title")
.with_where(where_filter)
.do()
)
print(query_result)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Article')
.withFields('title')
.withWhere({
operator: 'GreaterThan',
path: ['wordCount'],
valueInt: 1000,
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
title := graphql.Field{Name: "title"}
where := filters.Where().
WithPath([]string{"wordCount"}).
WithOperator(filters.GreaterThan).
WithValueInt(1000)
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Article").
WithFields(title).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field title = Field.builder().name("title").build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{ "wordCount" })
.operator(Operator.GreaterThan)
.valueInt(1000)
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Article")
.withFields(title)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Article(where: {
path: [\"wordCount\"],
operator: GreaterThan,
valueInt: 1000
}) {
title
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Article(where: {
path: ["wordCount"], # Path to the property that should be used
operator: GreaterThan, # operator
valueInt: 1000 # value (which is always = to the type of the path property)
}) {
title
}
}
}
Expected response
{
"data": {
"Get": {
"Article": [
{
"title": "Anywhere but Washington: an eye-opening journey in a deeply divided nation"
},
{
"title": "The world is still struggling to implement meaningful climate policy"
},
...
]
}
}
}
Filter structure
The where
filter is an algebraic object, which takes the following arguments:
Operator
(which takes one of the following values)And
Or
Equal
NotEqual
GreaterThan
GreaterThanEqual
LessThan
LessThanEqual
Like
WithinGeoRange
IsNull
ContainsAny
(*Only for array and text properties)ContainsAll
(*Only for array and text properties)
Path
: Is a list of strings in XPath style, indicating the property name of the collection.- If the property is a cross-reference, the path should be followed as a list of strings. For a
inPublication
reference property that refers toPublication
collection, the path selector forname
will be["inPublication", "Publication", "name"]
.
- If the property is a cross-reference, the path should be followed as a list of strings. For a
valueType
valueInt
: Forint
data type.valueBoolean
: Forboolean
data type.valueString
: Forstring
data type (note:string
has been deprecated).valueText
: Fortext
,uuid
,geoCoordinates
,phoneNumber
data types.valueNumber
: Fornumber
data type.valueDate
: Fordate
(ISO 8601 timestamp, formatted as RFC3339) data type.
If the operator is And
or Or
, the operands are a list of where
filters.
Example filter structure (GraphQL)
{
Get {
<Class>(where: {
operator: <operator>,
operands: [{
path: [path],
operator: <operator>
<valueType>: <value>
}, {
path: [<matchPath>],
operator: <operator>,
<valueType>: <value>
}]
}) {
<propertyWithBeacon> {
<property>
... on <ClassOfWhereBeaconGoesTo> {
<propertyOfClass>
}
}
}
}
}
Example response
{
"data": {
"Get": {
"Article": [
{
"title": "Opinion | John Lennon Told Them ‘Girls Don't Play Guitar.' He Was So Wrong."
}
]
}
},
"errors": null
}
Not
operatorWeaviate doesn't have an operator to invert a filter (e.g. Not Like ...
). If you would like us to add one, please upvote the issue.
Filter behaviors
Multi-word queries in Equal
filters
The behavior for the Equal
operator on multi-word textual properties in where
filters depends on the tokenization
of the property.
See the Schema property tokenization section for the difference between the available tokenization types.
Stopwords in text
filters
Starting with v1.12.0
you can configure your own stopword lists for the inverted index.
Multiple operands
You can set multiple operands or nest conditions.
You can filter datetimes similarly to numbers, with the valueDate
given as string
in RFC3339 format.
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
collection = client.collections.get("Article")
response = collection.query.fetch_objects(
filters=(
Filter.by_property("wordCount").greater_than(1000)
& Filter.by_property("title").like("*economy*")
),
limit=5,
)
for o in response.objects:
print(o.properties) # Inspect returned objects
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"operator": "And",
"operands": [{
"path": ["wordCount"],
"operator": "GreaterThan",
"valueInt": 1000
}, {
"path": ["title"],
"operator": "Like",
"valueText": "*economy*",
}]
}
response = (
client.query
.get("Article", "title")
.with_where(where_filter)
.do()
)
print(response)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Article')
.withFields('title')
.withWhere({
operator: 'And',
operands: [{
path: ['wordCount'],
operator: 'GreaterThan',
valueInt: 1000,
}, {
path: ['title'],
operator: 'Like',
valueText:'*economy*',
}],
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"time"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
title := graphql.Field{Name: "title"}
filterString := "*economy*"
if err != nil {
panic(err)
}
where := filters.Where().
WithOperator(filters.And).
WithOperands([]*filters.WhereBuilder{
filters.Where().
WithPath([]string{"wordCount"}).
WithOperator(filters.GreaterThan).
WithValueInt(1000),
filters.Where().
WithPath([]string{"title"}).
WithOperator(filters.Like).
WithValueText(filterString),
})
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Article").
WithFields(title).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field title = Field.builder().name("title").build();
WhereFilter wordCountGreaterThen = WhereFilter.builder()
.path(new String[]{ "wordCount" })
.operator(Operator.GreaterThan)
.valueInt(1000)
.build();
WhereFilter wordCountLike = WhereFilter.builder()
.path(new String[]{ "title" })
.operator(Operator.Like)
.valueText("*economy*")
.build();
WhereFilter where = WhereFilter.builder()
.operator(Operator.And)
.operands(new WhereFilter[]{ wordCountGreaterThen, wordCountLike })
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Article")
.withFields(title)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Article(where: {
operator: And,
operands: [{
path: [\"wordCount\"],
operator: GreaterThan,
valueInt: 1000
}, {
path: [\"title\"],
operator: Like,
valueText: \"*economy*\"
}]
}) {
title
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Article(where: {
operator: And,
operands: [{
path: ["wordCount"],
operator: GreaterThan,
valueInt: 1000
}, {
path: ["title"],
operator: Like,
valueText:"*economy*"
}]
}) {
title
}
}
}
Expected response
{
"data": {
"Get": {
"Article": [
{
"title": "China\u2019s long-distance lorry drivers are unsung heroes of its economy"
},
{
"title": "\u2018It\u2019s as if there\u2019s no Covid\u2019: Nepal defies pandemic amid a broken economy"
},
{
"title": "A tax hike threatens the health of Japan\u2019s economy"
}
]
}
}
}
Filter operators
Like
The Like
operator filters text
data based on partial matches. It can be used with the following wildcard characters:
?
-> exactly one unknown charactercar?
matchescart
,care
, but notcar
*
-> zero, one or more unknown characterscar*
matchescar
,care
,carpet
, etc*car*
matchescar
,healthcare
, etc.
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
collection = client.collections.get("Article")
response = collection.query.fetch_objects(
filters=Filter.by_property("title").like("New *"),
limit=5
)
for o in response.objects:
print(o.properties) # Inspect returned objects
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"path": ["name"],
"operator": "Like",
"valueText": "New *"
}
query_result = (
client.query
.get("Publication", "name")
.with_where(where_filter)
.do()
)
print(query_result)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Publication')
.withFields('name')
.withWhere({
path: ['name'],
operator: 'Like',
valueText: 'New *',
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
name := graphql.Field{Name: "name"}
where := filters.Where().
WithPath([]string{"name"}).
WithOperator(filters.Like).
WithValueString("New *")
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Publication").
WithFields(name).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field name = Field.builder().name("name").build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{ "name" })
.operator(Operator.Like)
.valueText("New *")
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Publication")
.withFields(name)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Publication(where: {
path: [\"name\"],
operator: Like,
valueText: \"New *\"
}) {
name
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Publication(where: {
path: ["name"],
operator: Like,
valueText: "New *"
}) {
name
}
}
}
Expected response
{
"data": {
"Get": {
"Publication": [
{
"name": "The New York Times Company"
},
{
"name": "International New York Times"
},
{
"name": "New York Times"
},
{
"name": "New Yorker"
}
]
}
}
}
Performance of Like
Each Like
filter iterates over the entire inverted index for that property. The search time will go up linearly with the dataset size, and may become slow for large datasets.
Wildcard literal matches with Like
Currently, the Like
filter is not able to match wildcard characters (?
and *
) as literal characters. For example, it is currently not possible to only match the string car*
and not car
, care
or carpet
. This is a known limitation and may be addressed in future versions of Weaviate.
ContainsAny
/ ContainsAll
The ContainsAny
and ContainsAll
operators filter objects using values of an array as criteria.
Both operators expect an array of values and return objects that match based on the input values.
ContainsAny
and ContainsAll
notes:- The
ContainsAny
andContainsAll
operators treat texts as an array. The text is split into an array of tokens based on the chosen tokenization scheme, and the search is performed on that array. - When using
ContainsAny
orContainsAll
with the REST api for batch deletion, the text array must be specified with thevalueTextArray
argument. This is different from the usage in search, where thevalueText
argument that can be used.
ContainsAny
ContainsAny
returns objects where at least one of the values from the input array is present.
Consider a dataset of Person
, where each object represents a person with a languages_spoken
property with a text
datatype.
A ContainsAny
query on a path of ["languages_spoken"]
with a value of ["Chinese", "French", "English"]
will return objects where at least one of those languages is present in the languages_spoken
array.
ContainsAll
ContainsAll
returns objects where all the values from the input array are present.
Using the same dataset of Person
objects as above, a ContainsAll
query on a path of ["languages_spoken"]
with a value of ["Chinese", "French", "English"]
will return objects where all three of those languages are present in the languages_spoken
array.
Filter performance
In some edge cases, filter performance may be slow due to a mismatch between the filter architecture and the data structure. For example, if a property has very large cardinality (i.e. a large number of unique values), its range-based filter performance may be slow.
If you are experiencing slow filter performance, we suggest further restricting your query by adding more conditions to the where
operator, or adding a limit
parameter to your query.
We are working on improving the performance of these filters in a future release. Please upvote this feature if this is important to you, so we can prioritize it accordingly.
Special cases
By id
You can filter object by their unique id or uuid, where you give the id
as valueText
.
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
collection = client.collections.get("Article")
response = collection.query.fetch_objects(
filters=Filter.by_id().equal("00037775-1432-35e5-bc59-443baaef7d80")
)
for o in response.objects:
print(o.properties) # Inspect returned objects
client.close()
import weaviate
import json
client = weaviate.Client("http://localhost:8080")
where_filter = {
"path": ["id"],
"operator": "Equal",
"valueText": "00037775-1432-35e5-bc59-443baaef7d80"
}
response = (
client.query
.get("Article", "title")
.with_where(where_filter)
.do()
)
print(json.dumps(response, indent=2))
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Article')
.withFields('title')
.withWhere({
operator: 'Equal',
path: ['id'],
valueText: '00037775-1432-35e5-bc59-443baaef7d80',
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
title := graphql.Field{Name: "title"}
where := filters.Where().
WithPath([]string{"id"}).
WithOperator(filters.Equal).
WithValueText("00037775-1432-35e5-bc59-443baaef7d80")
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Article").
WithFields(title).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field title = Field.builder().name("title").build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{ "id" })
.operator(Operator.Equal)
.valueText("00037775-1432-35e5-bc59-443baaef7d80")
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Article")
.withFields(title)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Article(where: {
path: [\"id\"],
operator: Equal,
valueText: \"00037775-1432-35e5-bc59-443baaef7d80\"
}) {
title
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Article(where: {
path: ["id"],
operator: Equal,
valueText: "00037775-1432-35e5-bc59-443baaef7d80"
}) {
title
}
}
}
Expected response
{
"data": {
"Get": {
"Article": [
{
"title": "Backs on the rack - Vast sums are wasted on treatments for back pain that make it worse"
}
]
}
}
}
By timestamps
Filtering can be performed with internal timestamps as well, such as creationTimeUnix
and lastUpdateTimeUnix
. These values can be represented either as Unix epoch milliseconds, or as RFC3339 formatted datetimes. Note that epoch milliseconds should be passed in as a valueText
, and an RFC3339 datetime should be a valueDate
.
Filtering by timestamp requires the target class to be configured to index timestamps. See here for details.
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
from datetime import datetime
client = weaviate.connect_to_local()
collection = client.collections.get("Article")
year2k = datetime.strptime("2000-01-01T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ")
response = collection.query.fetch_objects(
filters=Filter.by_creation_time().greater_or_equal(year2k),
return_metadata=MetadataQuery(creation_time=True),
limit=2
)
for o in response.objects:
print(o.properties) # Inspect returned objects
print(o.metadata) # Inspect returned creation time
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"path": ["_creationTimeUnix"],
"operator": "GreaterThan",
# "valueDate": "2022-03-18T20:26:34.586-05:00", # Can use either `valueDate` with a `RFC3339` datetime or `valueText` as Unix epoch milliseconds
"valueText": "1647653359063"
}
response = (
client.query
.get("Article", "title")
.with_where(where_filter)
.do()
)
print(response)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Article')
.withFields('title')
.withWhere({
operator: 'GreaterThan',
path: ['_creationTimeUnix'],
// valueDate: '2022-03-18T20:26:34.586-05:00',
// Can use either `valueDate` with a `RFC3339` datetime or `valueText` as Unix epoch milliseconds
valueText: '1647653359063',
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"time"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
title := graphql.Field{Name: "title"}
where := filters.Where().
WithPath([]string{"_creationTimeUnix"}).
WithOperator(filters.LessThan).
WithValueDate(time.Now()) // Can use either `valueDate` with a `RFC3339` datetime or `valueText` as Unix epoch milliseconds
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Article").
WithFields(title).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field title = Field.builder().name("title").build();
Date date;
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
date = df.parse("2022-03-18T20:26:34-0500");
} catch (ParseException e) {
throw new RuntimeException(e);
}
WhereFilter where = WhereFilter.builder()
.path(new String[]{ "_creationTimeUnix" })
.operator(Operator.GreaterThan)
.valueDate(date) // Can use either `valueDate` with a `RFC3339` datetime or `valueText` as Unix epoch milliseconds
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Article")
.withFields(title)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Article(where: {
path: [\"_creationTimeUnix\"],
operator: GreaterThan,
valueDate: \"2022-03-18T20:26:34.586-05:00\"
}) {
title
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Article(where: {
path: ["_creationTimeUnix"],
operator: GreaterThan,
valueText: "1647653359063" # can also use valueDate: "2022-03-18T20:26:34.586-05:00"
}) {
title
}
}
}
Expected response
{
"data": {
"Get": {
"Article": [
{
"title": "Army builds new body armor 14-times stronger in the face of enemy fire"
},
...
]
}
}
}
By property length
Filtering can be performed with the length of properties.
The length of properties is calculated differently depending on the type:
- array types: the number of entries in the array is used, where null (property not present) and empty arrays both have the length 0.
- strings and texts: the number of characters (unicode characters such as 世 count as one character).
- numbers, booleans, geo-coordinates, phone-numbers and data-blobs are not supported.
{
Get {
<Class>(
where: {
operator: <Operator>,
valueInt: <value>,
path: ["len(<property>)"]
}
)
}
}
Supported operators are (not) equal
and greater/less than (equal)
and values need to be 0 or larger.
Note that the path
value is a string, where the property name is wrapped in len()
. For example, to filter for objects based on the length of the title
property, you would use path: ["len(title)"]
.
To filter for Article
class objects with title
length greater than 10, you would use:
{
Get {
Article(
where: {
operator: GreaterThan,
valueInt: 10,
path: ["len(title)"]
}
)
}
}
Filtering by property length requires the target class to be configured to index the length.
By cross-references
You can also search for the value of the property of a cross-references, also called beacons.
For example, these filters select based on the class Article but who have inPublication
set to New Yorker.
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
collection = client.collections.get("Article")
response = collection.query.fetch_objects(
filters=Filter.by_ref(link_on="inPublication").by_property("name").like("*New*"),
return_references=QueryReference(link_on="inPublication", return_properties=["name"]),
limit=2
)
for o in response.objects:
print(o.properties) # Inspect returned objects
for ref_o in o.references["inPublication"].objects:
print(ref_o.properties)
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"path": ["inPublication", "Publication", "name"],
"operator": "Equal",
"valueText": "New Yorker"
}
query_result = (
client.query
.get("Article", ["title", "inPublication{... on Publication{name}}"])
.with_where(where_filter)
.do()
)
print(query_result)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Article')
.withFields('title inPublication{... on Publication{name}}')
.withWhere({
path: ['inPublication', 'Publication', 'name'],
operator: 'Equal',
valueText: 'New Yorker',
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
fields := []graphql.Field{
{Name: "title"},
{Name: "inPublication", Fields: []graphql.Field{
{Name: "... on Publication", Fields: []graphql.Field{
{Name: "name"}},
},
}},
}
where := filters.Where().
WithPath([]string{"inPublication", "Publication", "name"}).
WithOperator(filters.Equal).
WithValueString("New Yorker")
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Article").
WithFields(fields...).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field title = Field.builder().name("title").build();
Field inPublication = Field.builder()
.name("inPublication")
.fields(new Field[]{
Field.builder()
.name("... on Publication")
.fields(new Field[]{
Field.builder().name("name").build()
})
.build()
})
.build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{ "inPublication", "Publication", "name" })
.operator(Operator.Equal)
.valueText("New Yorker")
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Article")
.withFields(title, inPublication)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Article(where: {
path: [\"inPublication\", \"Publication\", \"name\"],
operator: Equal,
valueText: \"New Yorker\"
}) {
title
inPublication{
... on Publication{
name
}
}
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Article(where: {
path: ["inPublication", "Publication", "name"],
operator: Equal,
valueText: "New Yorker"
}) {
title
inPublication{
... on Publication{
name
}
}
}
}
}
Expected response
{
"data": {
"Get": {
"Article": [
{
"inPublication": [
{
"name": "New Yorker"
}
],
"title": "The Hidden Costs of Automated Thinking"
},
{
"inPublication": [
{
"name": "New Yorker"
}
],
"title": "The Real Deal Behind the U.S.\u2013Iran Prisoner Swap"
},
...
]
}
}
}
By count of reference
Above example shows how filter by reference can solve straightforward questions like "Find all articles that are published by New Yorker". But questions like "Find all articles that are written by authors that wrote at least two articles", cannot be answered by the above query structure. It is however possible to filter by reference count. To do so, simply provide one of the existing compare operators (Equal
, LessThan
, LessThanEqual
, GreaterThan
, GreaterThanEqual
) and use it directly on the reference element. For example:
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Java
- Go
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
response = collection.query.fetch_objects(
filters=Filter.by_ref_count(link_on="inPublication").greater_than(2),
return_references=QueryReference(link_on="inPublication", return_properties=["name"]),
limit=2
)
for o in response.objects:
print(o.properties) # Inspect returned objects
for ref_o in o.references["inPublication"].objects:
print(ref_o.properties)
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"valueInt": 2,
"operator": "GreaterThanEqual",
"path": ["writesFor"]
}
response = (
client.query
.get("Author", ["name", "writesFor {... on Publication { name }}"])
.with_where(where_filter)
.do()
)
print(response)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Author')
.withFields('name writesFor {... on Publication {name}}')
.withWhere({
valueInt: 2,
operator: 'GreaterThanEqual',
path: ['writesFor'],
})
.do();
console.log(response);
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field name = Field.builder().name("name").build();
Field wroteArticles = Field.builder()
.name("writesFor")
.fields(new Field[]{
Field.builder()
.name("... on Publication")
.fields(new Field[]{
Field.builder().name("name").build()
})
.build()
})
.build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{"writesFor"})
.operator(Operator.GreaterThanEqual)
.valueInt(2)
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Author")
.withFields(name, wroteArticles)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
package main
import (
"context"
"fmt"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
fields := []graphql.Field{
{Name: "name"},
{Name: "writesFor", Fields: []graphql.Field{
{Name: "... on Publication", Fields: []graphql.Field{
{Name: "name"},
}},
}},
}
where := filters.Where().
WithPath([]string{"writesFor"}).
WithOperator(filters.GreaterThanEqual).
WithValueInt(2)
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Author").
WithFields(fields...).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
echo '{
"query": "{
Get {
Author(
where:{
valueInt: 2
operator: GreaterThanEqual
path: [\"writesFor\"]
}
) {
name
writesFor {
... on Publication {
name
}
}
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Author(
where: {
valueInt: 2,
operator: GreaterThanEqual,
path: ["writesFor"]
}
) {
name
writesFor {
... on Publication {
name
}
}
}
}
}
Expected response
{
"data": {
"Get": {
"Author": [
{
"name": "Agam Shah",
"writesFor": [
{
"name": "Wall Street Journal"
},
{
"name": "Wall Street Journal"
}
]
},
{
"name": "Costas Paris",
"writesFor": [
{
"name": "Wall Street Journal"
},
{
"name": "Wall Street Journal"
}
]
},
...
]
}
}
}
By geo coordinates
A special case of the Where
filter is with geoCoordinates. This filter is only supported by the Get{}
function. If you've set the geoCoordinates
property type, you can search in an area based on kilometers.
For example, this curious returns all in a radius of 2KM around a specific geo-location:
- Python Client v4
- Python Client v3
- JS/TS Client v2
- Go
- Java
- Curl
- GraphQL
import weaviate
from weaviate.classes.query import Filter, GeoCoordinate, MetadataQuery, QueryReference # Import classes as needed
import os
client = weaviate.connect_to_local()
response = publications.query.fetch_objects(
filters=(
Filter
.by_property("headquartersGeoLocation")
.within_geo_range(
coordinate=GeoCoordinate(
latitude=33.7579,
longitude=84.3948
),
distance=10000 # In meters
)
),
)
for o in response.objects:
print(o.properties) # Inspect returned objects
client.close()
import weaviate
client = weaviate.Client("http://localhost:8080")
get_articles_where = """
{
Get {
Publication(where: {
operator: WithinGeoRange,
valueGeoRange: {
geoCoordinates: {
latitude: 51.51, # latitude
longitude: -0.09 # longitude
},
distance: {
max: 2000 # distance in meters
}
},
path: ["headquartersGeoLocation"] # property needs to be of geoLocation type.
}) {
name
headquartersGeoLocation {
latitude
longitude
}
}
}
}
"""
query_result = client.query.raw(get_articles_where)
print(query_result)
import weaviate from 'weaviate-ts-client';
const client = weaviate.client({
scheme: 'http',
host: 'localhost:8080',
});
const response = await client.graphql
.get()
.withClassName('Publication')
.withFields('name headquartersGeoLocation {latitude longitude}')
.withWhere({
operator: 'WithinGeoRange',
path: ['headquartersGeoLocation'],
valueGeoRange: {
geoCoordinates: {
latitude: 51.51,
longitude: -0.09,
},
distance: {
max: 2000,
},
},
})
.do();
console.log(response);
package main
import (
"context"
"fmt"
"github.com/weaviate/weaviate-go-client/v4/weaviate"
"github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
"github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
)
func main() {
cfg := weaviate.Config{
Host: "localhost:8080",
Scheme: "http",
}
client, err := weaviate.NewClient(cfg)
if err != nil {
panic(err)
}
fields := []graphql.Field{
{Name: "name"},
{Name: "headquartersGeoLocation", Fields: []graphql.Field{
{Name: "latitude"},
{Name: "longitude"},
}},
}
where := filters.Where().
WithOperator(filters.WithinGeoRange).
WithPath([]string{"headquartersGeoLocation"}).
WithValueGeoRange(&filters.GeoCoordinatesParameter{
Latitude: 51.51,
Longitude: -0.09,
MaxDistance: 2000,
})
ctx := context.Background()
result, err := client.GraphQL().Get().
WithClassName("Publication").
WithFields(fields...).
WithWhere(where).
Do(ctx)
if err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
package io.weaviate;
import io.weaviate.client.Config;
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.v1.filters.Operator;
import io.weaviate.client.v1.filters.WhereFilter;
import io.weaviate.client.v1.graphql.model.GraphQLResponse;
import io.weaviate.client.v1.graphql.query.fields.Field;
public class App {
public static void main(String[] args) {
Config config = new Config("http", "localhost:8080");
WeaviateClient client = new WeaviateClient(config);
Field name = Field.builder().name("name").build();
Field headquartersGeoLocation = Field.builder()
.name("headquartersGeoLocation")
.fields(new Field[]{
Field.builder().name("latitude").build(),
Field.builder().name("longitude").build()
})
.build();
WhereFilter where = WhereFilter.builder()
.path(new String[]{ "add" })
.operator(Operator.WithinGeoRange)
.valueGeoRange(WhereFilter.GeoRange.builder()
.geoCoordinates(WhereFilter.GeoCoordinates.builder()
.latitude(51.51f)
.longitude(-0.09f)
.build())
.distance(WhereFilter.GeoDistance.builder()
.max(2000f)
.build())
.build())
.build();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("Publication")
.withFields(name, headquartersGeoLocation)
.withWhere(where)
.run();
if (result.hasErrors()) {
System.out.println(result.getError());
return;
}
System.out.println(result.getResult());
}
}
echo '{
"query": "{
Get {
Publication(where: {
operator: WithinGeoRange,
valueGeoRange: {
geoCoordinates: {
latitude: 51.51,
longitude: -0.09
},
distance: {
max: 2000
}
},
path: [\"headquartersGeoLocation\"]
}) {
name
headquartersGeoLocation {
latitude
longitude
}
}
}
}"
}' | curl \
-X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer learn-weaviate' \
-d @- \
https://edu-demo.weaviate.network/v1/graphql
{
Get {
Publication(where: {
operator: WithinGeoRange,
valueGeoRange: {
geoCoordinates: {
latitude: 51.51, # latitude
longitude: -0.09 # longitude
},
distance: {
max: 2000 # distance in meters
}
},
path: ["headquartersGeoLocation"] # property needs to be of geoLocation type.
}) {
name
headquartersGeoLocation {
latitude
longitude
}
}
}
}
Expected response
{
"data": {
"Get": {
"Publication": [
{
"headquartersGeoLocation": {
"latitude": 51.512737,
"longitude": -0.0962234
},
"name": "Financial Times"
},
{
"headquartersGeoLocation": {
"latitude": 51.512737,
"longitude": -0.0962234
},
"name": "International New York Times"
}
]
}
}
}
Note that geoCoordinates
uses a vector index under the hood.
Currently, geo-coordinate filtering is limited to the nearest 800 results from the source location, which will be further reduced by any other filter conditions and search parameters.
If you plan on a densely populated dataset, consider using another strategy such as geo-hashing into a text
datatype, and filtering further, such as with a ContainsAny
filter.
By null state
Using the IsNull
operator allows you to do filter for objects where given properties are null
or not null
. Note that zero-length arrays and empty strings are equivalent to a null value.
{
Get {
<Class>(where: {
operator: IsNull,
valueBoolean: <true/false>
path: [<property>]
}
}
Filtering by null-state requires the target class to be configured to index this. See here for details.
Related pages
Questions and feedback
If you have any questions or feedback, let us know in the user forum.