Nested UNWIND - выборочное поведение для не-списков. Как это возможно? - PullRequest
0 голосов
/ 24 августа 2018

Это сводит меня с ума, особенно потому, что ломает мою ментальную модель работы Neo4j.

1. Ошибка: размотка (5)

С инструкция :

Попытка использовать UNWIND в выражении, которое не возвращает список, например UNWIND 5, приведет к ошибке.

Действительно:

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. Работы: раскрутить ([1, [2, 3]])

Так же, как подготовка к следующему шагу:

WITH [1, [2,3]] AS x 
UNWIND x AS y 
RETURN y

Плюет:

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

Обратите внимание, что первая строка 1 - не список.

3. Работы: раскручивать (раскручивать ([1, [2, 3]])) *

Surprise

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

Выходы:

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

Так что Neo в порядке с 1 во вложенном раскручивании.

4. Ошибка: размотка (размотка ([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 "
        ^

Как это возможно?

Я просто не могу понять, как в ленивом контексте разматывание может выборочно завершиться неудачей, если элемент не является списком, но только до тех пор, пока ни одна из (повторяющихся) строк не включает список.

Другими словами, почему 1 в случае 3 в порядке, но не в случае 4?

Для тех, кто заинтересован, вот код для размотки трубы . Там нет ничего, чтобы предположить, как происходит волшебство.

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()
        }
      }
    }
  }
}

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

К вашему сведению, если вы используете параметры в своем запросе, 1) работает!

:params { data:5}

WITH $data AS x 
UNWIND x AS y 
RETURN y
0 голосов
/ 31 августа 2018

Если я прочитаю сообщение об ошибке, которое вы отправилиy AS z "

и затем я замечаю, что вы разместили код для UnwindPipe, похоже, что вы смотрите на дерево и упускаете лес.

Итак, позвольте мне объяснитьчто я имею в виду.Я так понимаю, что вы подробно смотрите на код для UnwindPipe и нигде не видите причину ошибки.Однако в сообщении об ошибке указывается, что у вас SyntaxError, а не Run time error.Вы уже видите свою проблему?

Парсер команды достаточно умен, чтобы знать, что вы дали список первому UNWIND, а затем достаточно умен, чтобы понять, что результат этого не список,все же второй UNWIND нуждается в списке, и, следовательно, анализатор отвечает сообщением об ошибке.Код для UnwindPipe никогда не вызывался и не выполнялся, поскольку анализ входной команды не удался.

...