Neo4jClient ICypherFluentQuery 似乎不适用于可空值

问题描述 投票:0回答:1

我正在编写一个密码查询,我想找到在给定日期范围内担任特定角色的所有用户。看起来

null
查询有点棘手。

考虑以下代码:

public async Task<Result<IEnumerable<UserNode>>> FindUsersByRoleNameAsync(
    string roleName, 
    DateOnly? from = default, 
    DateOnly? until = default, 
    CancellationToken token = default)
{
    from ??= DateOnly.MinValue;
    until ??= DateOnly.MaxValue;

    return await client.Cypher
        .Match("(user:User)-[edge:has_role]-(role:Role)")
        .Where((RoleNode role) => role.Name == roleName)
        .AndWhere((HasRole edge) => edge.From >= from)
        .AndWhere((HasRole edge) => edge.Until <= until) // this line is problematic!
        .ToNodesAsync<UserNode>("user", UnitOfWork, token) // Custom deserialization...ignore.
        .ConfigureAwait(false);
}

故障解释...

  • 该方法接受默认的
    DateOnly?
    参数
    from
    until
    ,可以在查询中省略。
  • 如果省略
    from
    ,则将其设置为
    DateOnly.MinValue
    (实际上,在 01/01/0001 之前没有人会拥有角色)
  • 如果省略
    until
    ,则设置为
    DateOnly.MaxValue
    (实际上,在 31/12/9999 之后没有人会拥有角色)

一些上下文可能有助于解释为什么

null
似乎是问题所在;

  • HasRole.From
    DateOnly
  • HasRole.Until
    DateOnly?
    ,其中
    null
    表示该角色仍然适用。

如果我从查询中省略这一行...

.AndWhere((HasRole edge) => edge.Until <= until) // this line is problematic!

...那么它适用于省略

from
until
的查询,以及
from
not 省略的查询。

似乎不起作用的一点是当尝试将

edge.Until
(可能是数据库中的
null
)与
until
(这将是指定值,或者如果省略则为
DateOnly.MaxValue
)进行比较时.

删除上面的行,2/3 的查询测试通过。 重新添加该行会导致 0/3 查询测试通过。

我做错了什么?

c# neo4j cypher neo4jclient
1个回答
0
投票

值得查看从代码生成的实际查询,它类似于:

MATCH (user: User)-[edge:has_role]-(role:Role)
WHERE (role.Name = "Blah")
AND (edge.From >= "")
AND (edge.Until <= "9999-12-31")

所以它总是期待

Until
存在。您需要将查询更改为:

MATCH (user:User)-[edge:has_role]-(role:Role)
WHERE (role.Name = "Blah")
AND (edge. From >= "")
AND (edge. Until IS NULL) 
OR (edge. Until <= "9999-12-31")

客户端正在按照您的要求进行操作,找到任何

HasRole
属性小于
Until
DateOnly.MaxValue
边,并写入相应的 Cypher。

也许这样的东西就是你想要的:

public async Task<Result<IEnumerable<UserNode>>> FindUsersByRoleNameAsync(
    string roleName,
    DateOnly? from = default,
    DateOnly? until = default,
    CancellationToken token = default)
{
    from ??= DateOnly.MinValue;
    until ??= DateOnly.MaxValue;

    return await client.Cypher
        .Match("(user:User)-[edge:has_role]-(role:Role)")
        .Where((RoleNode role) => role.Name == roleName)
        .AndWhere((HasRole edge) => edge.From >= from)
        .AndWhere((HasRole edge) => edge.Until <= until) // this line is problematic!
        .OrWhere($"edge.{nameof(HasRole.Until)} IS NULL") //Add here
        .ToNodesAsync<UserNode>("user", UnitOfWork, token) // Custom deserialization...ignore.
        .ConfigureAwait(false);
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.