这让我发疯了,特别是因为它打破了我关于Neo4j工作原理的思维模式。

1.失败:放松(5)

the manual:



确实:

WITH 5 AS x
UNWIND x AS y
RETURN y

产量:
Neo.ClientError.Statement.SyntaxError: Type mismatch: expected List<T> but was Integer (line 2, column 8 (offset: 20))
"UNWIND x AS y "
        ^

2.作品:unwind([1,[2,3]])

只是为下一步做准备:
WITH [1, [2,3]] AS x
UNWIND x AS y
RETURN y

吐口水:
╒═════╕
│"y"  │
╞═════╡
│1    │
├─────┤
│[2,3]│
└─────┘

请注意,第一行是1-不是列表。

3.作品:unwind(unwind([1,[2,3]])

惊讶吗
WITH [1, [2,3]] AS x
UNWIND x AS y
UNWIND y AS z
RETURN z

输出:
╒═══╕
│"z"│
╞═══╡
│1  │
├───┤
│2  │
├───┤
│3  │
└───┘

因此Neo可以嵌套嵌套展开中的1来使用。

4.失败:unwind(unwind([1,2]))
WITH [1, 2] AS x
UNWIND x AS y
UNWIND y AS z
RETURN z

错误:
Neo.ClientError.Statement.SyntaxError: Type mismatch: expected List<T> but was Integer (line 3, column 8 (offset: 40))
"UNWIND y AS z "
        ^

这怎么可能?

我只是不明白,在懒惰的上下文中,如果某项不是列表,则展开可能会选择性地失败,但是直到(迭代)行中没有一个涉及列表的时间如此长。

换句话说,情况3的1为什么可以,但情况4的ojit_code没问题?

对于那些感兴趣的人,here's the code for the unwind pipe。没有任何迹象表明魔术是如何发生的。
case class UnwindPipe(source: Pipe, collection: Expression, variable: String)
                     (val id: Id = Id.INVALID_ID)
  extends PipeWithSource(source) with ListSupport {

  collection.registerOwningPipe(this)

  protected def internalCreateResults(input: Iterator[ExecutionContext], state: QueryState): Iterator[ExecutionContext] = {
    if (input.hasNext) new UnwindIterator(input, state) else Iterator.empty
  }

  private class UnwindIterator(input: Iterator[ExecutionContext], state: QueryState) extends Iterator[ExecutionContext] {
    private var context: ExecutionContext = _
    private var unwindIterator: Iterator[AnyValue] = _
    private var nextItem: ExecutionContext = _

    prefetch()

    override def hasNext: Boolean = nextItem != null

    override def next(): ExecutionContext = {
      if (hasNext) {
        val ret = nextItem
        prefetch()
        ret
      } else Iterator.empty.next()
    }

    @tailrec
    private def prefetch() {
      nextItem = null
      if (unwindIterator != null && unwindIterator.hasNext) {
        nextItem = executionContextFactory.copyWith(context, variable, unwindIterator.next())
      } else {
        if (input.hasNext) {
          context = input.next()
          unwindIterator = makeTraversable(collection(context, state)).iterator.asScala
          prefetch()
        }
      }
    }
  }
}

最佳答案

如果我阅读了您发布的错误消息



然后我注意到您发布了UnwindPipe的代码,看来您正在看一棵树,却错过了森林。

所以,让我解释一下我的意思。我认为您正在详细查看UnwindPipe的代码,而在代码中的任何位置都看不到错误的原因。但是,错误消息指出您有一个SyntaxError而不是Run time error。你看到你的问题了吗?

该命令的解析器足够聪明,可以知道您给第一个UNWIND提供了一个列表,然后又足够聪明,可以知道它的结果不是列表,但是第二个UNWIND需要一个列表,因此解析器使用错误信息。由于解析输入命令失败,因此从未调用或执行UnwindPipe的代码。

08-06 17:44