过滤

查询数据时,可在查询或变异的 where 参数中的类型上使用许多运算符,以便过滤查询结果或指定变异适用的对象集。

运算符可以是独立运算符(参见 布尔运算符),也可以附加到字段名称(例如,字符串比较)。

所有运算符都可以使用布尔运算符 ANDORNOT 组合。

运算符

布尔运算符

作为独立运算符,布尔运算符接受一个数组参数,该参数包含与 where 参数格式相同的项目。这样,它们可以嵌套以形成复杂的布尔表达式。

例如,如果您想匹配所有演员,无论是姓名为“基努”还是不属于“潘托利安诺”家族,他们在“黑客帝国”电影中扮演过角色,您可以这样查询:

query {
    actors(where: {
        AND: [
            {
                OR: [
                    { name_CONTAINS: "Keanu" },
                    { NOT: { name_ENDS_WITH: "Pantoliano" } }
                ]
            },
            {
                movies_SOME: { title: "The Matrix" }
            }
        ]}
    ) {
        name
        movies {
            title
        }
    }
}

name_CONTAINSname_ENDS_WITH字符串比较,而 movies_SOME关系过滤器

等式运算符

所有类型都可以测试相等或不相等。

例如

过滤所有名为 John 的用户
query {
  users(where: {name: "John" })
    id
    name
  }

对于不相等,您必须使用 NOT 逻辑运算符。

过滤所有未命名为 John 的用户
query {
  users(where: { NOT: {name: "John" }})
    id
    name
  }

对于 Boolean 类型,等式运算符是唯一可用的运算符。

数值运算符

这些是针对数字 (IntFloatBigInt)、时间空间 类型可用的运算符

  • _LT

  • _LTE

  • _GT

  • _GTE

以下是使用方法示例

过滤年龄小于 50 岁的用户
query {
  users(where: {age_LT: 50 }) {
    id
    name
    age
  }
}

空间类型对数值过滤的使用方式不同,并且还有一些其他选项。有关更多信息,请参见 过滤空间类型

空间类型过滤

PointCartesianPoint 类型都使用 数值运算符 并具有一个额外的 _DISTANCE 过滤器。以下是两种类型中每个过滤器执行的操作列表

  • _LT:检查点是否小于 distance 字段中指定的距离(以米为单位)远离 point 字段中指定的点。

  • _LTE:检查点是否小于或等于 distance 字段中指定的距离(以米为单位)远离 point 字段中指定的点。

  • _DISTANCE:检查点是否与 distance 字段中指定的距离(以米为单位)远离 point 字段中指定的点完全相同。

  • _GT:检查点是否大于 distance 字段中指定的距离(以米为单位)远离 point 字段中指定的点。

  • _GTE:检查点是否大于或等于 distance 字段中指定的距离(以米为单位)远离 point 字段中指定的点。

对于 Point 类型,所有过滤器都采用以下类型作为参数

input PointDistance {
    point: Point!
    distance: Float!
}

在实践中,您可以构建如下查询,该查询查找距离 Point 5 公里(5000 米)半径内的所有用户

query CloseByUsers($longitude: Float!, $latitude: Float!) {
    users(where: { location_LTE: { point: { longitude: $longitude, latitude: $latitude }, distance: 5000 } }) {
        name
        location {
            longitude
            latitude
        }
    }
}

类似地,对于 CartesianPoint 类型,所有过滤器都采用以下类型作为参数

input CartesianPointDistance {
    point: CartesianPoint!
    distance: Float!
}

CartesianPoint 的相同查询

query CloseByUsers($x: Float!, $y: Float!) {
  users(where: { location_LTE: { point: { x: $x, y: $y }, distance: 5000 } }) {
    name
    location {
      x
      y
    }
  }
}

类型比较

字符串比较

以下区分大小写的比较运算符可用于 StringID 类型

  • _STARTS_WITH

  • _ENDS_WITH

  • _CONTAINS

以下是使用方法示例

过滤名称以“J”开头的用户
query {
  users(where: { name_STARTS_WITH: "J" }) {
    id
    name
  }
}

此外,数值运算符可用于字符串比较。它们默认情况下处于禁用状态。要启用它们,请将它们添加到 Stringfilters 特性选项中

const { Neo4jGraphQL } = require("@neo4j/graphql");
const neo4j = require("neo4j-driver");

const typeDefs = `
    type User {
        name: String
    }
`;

const driver = neo4j.driver(
    "bolt://localhost:7687",
    neo4j.auth.basic("username", "password")
);

const features = {
    filters: {
        String: {
            LT: true,
            GT: true,
            LTE: true,
            GTE: true
        }
    }
};

const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver });

正则表达式匹配

过滤器 _MATCHES 可用于 StringID 类型的比较。它接受正则表达式字符串作为参数并返回所有匹配项。

请注意,正则表达式匹配过滤器默认情况下处于禁用状态。这是因为,在未受保护的 API 上,它们可能会被用来对支持的 Neo4j 数据库执行 ReDoS 攻击

如果您想启用正则表达式匹配,请更新 features 配置对象。

对于 String

const features = {
    filters: {
        String: {
            MATCHES: true,
        }
    }
};

const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver });

对于 ID

const features = {
    filters: {
        ID: {
            MATCHES: true,
        }
    }
};

const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver });

对于 StringID

const features = {
    filters: {
        String: {
            MATCHES: true,
        },
        ID: {
            MATCHES: true,
        }
    }
};

const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver });

数组比较

考虑以下类型定义

type Movie {
    id: ID!
    title: String!
    genres: [String!]
    year: Int!
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN)
}

type Actor {
    id: ID!
    name: String!
    movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}

_IN 运算符可用于非数组字段,并接受一个数组参数

query {
  movies(where: { year_IN: [1999, 2000, 2001] }) {
    title
    year
  }
}

该查询将返回所有在 1999 年、2000 年和 2001 年上映的电影。

相反,_INCLUDES 运算符可用于数组字段,并接受一个参数

query {
  movies(where: { genres_INCLUDES: "Action" }) {
    title
    genres
  }
}

该查询将返回所有包含“动作”作为其类型之一的电影。

_IN_INCLUDES 可用于除 Boolean 之外的所有类型。

接口过滤

您可以使用 typename_IN 过滤器过滤接口。有关更多详细信息和示例,请参见 类型定义 → 类型 → 接口

关系过滤

关系过滤取决于关系类型

  • n..1:通过在 field 上指定过滤器来对相关节点的相等或不相等进行过滤。

  • n..m:对相关节点列表进行过滤,并基于 Cypher 中可用的 列表谓词

例如,请考虑以下类型定义

type User {
    id: ID!
    name: String
    posts: [Post!]! @relationship(type: "HAS_POST", direction: OUT)
}

type Post {
    id: ID!
    content: String
    author: User! @relationship(type: "HAS_POST", direction: IN)
    likes: [User!]! @relationship(type: "LIKES", direction: IN)
}

n..1 关系

在类型定义示例中,author 代表 Post 上的 n..1 关系,其中给定的 Post 由一个且只有一个 author 创作。可用的过滤器是 author

例如

查找由所需作者撰写的帖子
query {
    posts(where: { author: { id: "7CF1D9D6-E527-4ACD-9C2A-207AE0F5CB8C" } }) {
        content
    }
}
查找所有 NOT 由不受欢迎的作者撰写的帖子
query {
    posts(where: { NOT: { author: { id: "7CF1D9D6-E527-4ACD-9C2A-207AE0F5CB8C" } } }) {
        content
    }
}

n..m 关系

在类型定义示例中,posts 代表 User 上的 n..m 关系,其中给定的 User 可以拥有任意数量的 posts

例如

查找所有用户,其中他们的所有帖子都包含搜索词:"neo4j"
query {
    users(where: { posts_ALL: { content_CONTAINS: "neo4j" } }) {
        name
    }
}
查找所有用户,其中他们的所有帖子都不包含搜索词:"cypher"
query {
    users(where: { posts_NONE: { content_CONTAINS: "cypher" } }) {
        name
    }
}
查找所有用户,其中他们的部分帖子包含搜索词:"graphql"
query {
    users(where: { posts_SOME: { content_CONTAINS: "graphql" } }) {
        name
    }
}
查找所有仅有一篇帖子包含搜索词“graph”的用户
query {
    users(where: { posts_SINGLE: { content_CONTAINS: "graph" } }) {
        name
    }
}

聚合过滤

Neo4j GraphQL 库在每个关系的where参数中提供了一个聚合键。您可以在关系的nodeedge上使用它。

以下是一些关于如何应用这种过滤的示例

  1. 查找点赞数大于5的帖子

    模式示例
    type User {
        name: String
    }
    
    type Post {
        content: String
        likes: [User!]! @relationship(type: "LIKES", direction: IN)
    }
    查询
    query {
        posts(where: { likesAggregate: { count_GT: 5 } }) {
            content
        }
    }
  2. 查找平均乘客年龄大于或等于18岁的航班

    模式示例
    type Passenger {
        name: String
        age: Int
    }
    
    type Flight {
        code: String
        passengers: [Passenger!]! @relationship(type: "FLYING_ON", direction: IN)
    }
    查询
    query {
        flights(where: { passengersAggregate: { node: { age_AVERAGE_GTE: 18 } } }) {
            code
        }
    }
  3. 查找演员最短时长少于10分钟的电影

    模式示例
    type Movie {
        title: String
        actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn")
    }
    
    type Person {
        name: String
    }
    
    type ActedIn @relationshipProperties {
        screenTime: Int
    }
    查询
    query {
        movies(where: { actorsAggregate: { edge: { screenTime_MIN_LT: 10 } } }) {
            title
        }
    }

使用运算符

聚合过滤也可以使用运算符完成。它们提供针对指定关系的nodeedge上每个类型可用的自动生成过滤器。

字段类型 描述 运算符 示例

count

where聚合中的一个特殊的“顶级”键,对所有关系都可用。用于计算父节点连接的关系数量。

count_EQUAL, count_GT, count_GTE, count_LT, count_LTE

query {
    posts(where: { likesAggregate: { count_GT: 5 } }) {
        content
    }
}

字符串

这些运算符针对每个字符串的长度进行计算。

_AVERAGE_LENGTH_EQUAL _AVERAGE_LENGTH_GT _AVERAGE_LENGTH_GTE _AVERAGE_LENGTH_LT _AVERAGE_LENGTH_LTE _SHORTEST_LENGTH_EQUAL _SHORTEST_LENGTH_GT _SHORTEST_LENGTH_GTE _SHORTEST_LENGTH_LT _SHORTEST_LENGTH_LTE _LONGEST_LENGTH_EQUAL _LONGEST_LENGTH_GT _LONGEST_LENGTH_GTE _LONGEST_LENGTH_LT _LONGEST_LENGTH_LTE

query {
    posts(where: { likesAggregate: { node: { name_LONGEST_LENGTH_GT: 5 } } }) {
        content
    }
}

数值

用于Int, FloatBigInt的情况。

_AVERAGE_EQUAL, _AVERAGE_GT, _AVERAGE_GTE, _AVERAGE_LT, _AVERAGE_LTE, _SUM_EQUAL, _SUM_GT, _SUM_GTE, _SUM_LT, _SUM_LTE, _MIN_EQUAL, _MIN_GT, _MIN_GTE, _MIN_LT, _MIN_LTE, _MAX_EQUAL, _MAX_GT, _MAX_GTE, _MAX_LT, _MAX_LTE

query {
    movies(where: { actorsAggregate: { edge: { screenTime_MIN_LT: 10 } } }) {
        title
    }
}

时间

用于DateTime, LocalDateTime, LocalTime, TimeDuration的情况。

_MIN_EQUAL, _MIN_GT, _MIN_GTE, _MIN_LT, _MIN_LTE, _MAX_EQUAL, _MAX_GT, _MAX_GTE, _MAX_LT, _MAX_LTE

类型定义
type Event {
    title: String!
    startTime: DateTime!
}
查询
query EventsAggregate {
    users(where: { eventsAggregate: { node: { startTime_GT: "2022-08-14T15:00:00Z" } } }) {
        name
    }
}

Duration

描述。

_AVERAGE_EQUAL, _AVERAGE_GT, _AVERAGE_GTE, _AVERAGE_LT, _AVERAGE_LTE

类型定义
type Event {
    title: String!
    duration: Duration!
}
查询
query EventsAggregate {
    users(where: { eventsAggregate: { node: { duration_AVERAGE_LT: "PT2H" } } }) {
        name
    }
}

ID

ID不可用聚合过滤器。

-

-