FQL 핵심 개념 섹션 4: 범위 조회 및 고급 필터링

Range()에서 간략하게 소개했습니다previous article. 제가 약속한 바와 같이 오늘 우리는 그것을 더욱 깊이 있게 이해할 것입니다.
이 시리즈는 당신이 기본 지식을 습득했다고 가정합니다.만약 당신이 Fauna DB와/또는 FQL의 초보자라면, 이것은 제가 FQL에 있는 것입니다introductory series.

본문:

  • 범위 조회 안내
  • 다중 항목 경계
  • 범위, 필터링
  • 색인 및 범위
  • 조합 인덱스
  • 인덱스 바인딩 범위
  • 범위 조회 안내


    범위 조회의 사상은 두 개의 경계를 제공함으로써 결과를 필터링하여 시작 값과 끝 값을 표시하는 것이다.FaunaDB는 결과를 포함할 시기를 결정하기 위해 값을 비교해야 하기 때문에 이러한 경계는 숫자, 문자열, 날짜 등 다른 값FQL types이 아니라 부울 값이어야 합니다.
    Range()의 작동 방식에 대해 알아보기 위해 데이터를 작성합니다.
    > CreateCollection({
      name: "Alphabet"
    })
    
    Map () 을 사용하여 문서를 추가합니다.
    > Map(
      [
        {leter: "A", position: 1},
        {leter: "B", position: 2},
        {leter: "C", position: 3},
        {leter: "D", position: 4},
        {leter: "E", position: 5},
        {leter: "F", position: 6},
        {leter: "G", position: 7},
        {leter: "H", position: 8},
        {leter: "I", position: 9},
        {leter: "J", position: 10}
      ],
      Lambda(
        "data",
        Create(
          Collection("Alphabet"),
          {data: Var("data")}
        )
      )
    )
    
    문서를 조회하려면 색인이 필요합니다.
    > CreateIndex({
        name: "Alphabet_by_letter_position",
        source: Collection("Alphabet"),
        values: [
          {field: ['data', 'letter']},
          {field: ['data', 'position']}
        ]
    })
    
    색인을 값을 되돌려주도록 설정했습니다.Range () 는 이러한 값을 경계와 비교해야 합니다.값 필드에 대한 자세한 내용은 CreateIndex() 문서를 참조하십시오.
    기본적으로 색인이 반환된 결과입니다.
    > Paginate(Match(Index("Alphabet_by_letter_position")))
    
    {
      data: [
        ["A", 1],
        ["B", 2],
        ["C", 3],
        ["D", 4],
        ["E", 5],
        ["F", 6],
        ["G", 7],
        ["H", 8],
        ["I", 9],
        ["J", 10]
      ]
    }
    
    우리는 지금 첫 번째 범위 조회를 진행할 준비를 하고 있다.각 경계에 대해 Range()는 개별 측정 값 또는 배열을 적용합니다.이제 A와 E의 단일 값을 사용합니다.
    > Paginate(
      Range(
        Match(Index("Alphabet_by_letter_position")),
        "A",
        "E"
      )
    )
    
    {
      data: [
        ["A", 1],
        ["B", 2],
        ["C", 3],
        ["D", 4],
        ["E", 5]
      ]
    }
    
    보시다시피 Range()는 시작 값과 끝 값을 각 결과의 첫 번째 항목과 비교하여 정의된 경계 내에 있는 결과를 필터링합니다.

    문자열 "A"가 "A"의 시작 값보다 우수하거나 같기 때문에 결과에는 ["A", 1]이 포함됩니다.마찬가지로 문자열 "F"가 "E"의 끝값보다 우수하기 때문에 결과에는 [F], 6] 이 포함되지 않습니다.
    경계의 단일 값이 아니라 단일 항목이 있는 그룹을 사용할 수도 있습니다.결과는 같다.
    > Paginate(
      Range(
        Match(Index("Alphabet_by_letter_position")),
        ["A"],
        ["E"]
      )
    )
    
    {
      data: [
        ["A", 1],
        ["B", 2],
        ["C", 3],
        ["D", 4],
        ["E", 5]
      ]
    }
    
    FaunaDB에서 첫 번째 또는 마지막 결과를 경계의 시작 값이나 끝 값으로 각각 사용하도록 공수 그룹을 사용할 수도 있습니다.이 경우 첫 번째 결과에서 "C"사이의 모든 결과를 얻을 수 있습니다.
    > Paginate(
      Range(
        Match(Index("Alphabet_by_letter_position")),
        [],
        "C"
      )
    )
    
    {
      data: [
        ["A", 1],
        ["B", 2],
        ["C", 3]
      ]
    }
    

    다중 항목 경계


    Range()의 흥미로운 점은 여러 개의 값을 가진 그룹을 경계로 사용할 수 있다는 것이다.결과는 아마 네가 바라는 것이 아닐 것이다!
    이 예제를 참조하십시오.
    > Paginate(
      Range(
        Match(Index("Alphabet_by_letter_position")),
        ["A", 3],
        ["G", 4]
      )
    )
    
    {
      data: [
        ["B", 2],
        ["C", 3],
        ["D", 4],
        ["E", 5],
        ["F", 6]
      ]
    }
    
    이 검색을 처음 실행할 때, 나는 곤혹스러웠다. 왜냐하면 나는 시작/종료 그룹의 모든 항목이 자신의 범위 필터로 충당하기를 원하기 때문이다. 라고 말할 수 있지만,range () 는 이렇게 작동하지 않는다.
    각 시작/종료 그룹은 실제로 하나의 값으로 사용되어 어떤 결과가 우수하거나 낮은지 확인합니다.

    보시다시피 FaunaDB는 [F], 6]이 [G], 4]의 상한선보다 낮다고 생각하지만 어떻게 작동합니까?
    그렇게 생각해.문자열을 알파벳순으로 정렬하면 "A8"또는 "Z1"중 어느 것이 첫 번째로 나열됩니까?분명히 "A8"이다. 왜냐하면 A가 Z 이전에 있었기 때문이다. 그렇지?정렬할 때 첫 번째 문자는 가장 높은 우선순위를 가지기 때문에, 우리는 두 번째 문자가 첫 번째 문자열에 있는지 확인하는 데 관심이 없다.
    이것 또한 FaunaDB가 [G], 7]이 [G], 4보다 낫다고 생각하고 결과에서 배제한 이유를 설명한다.첫 번째 항목이 같기 때문에 두 번째 항목만 비교에 영향을 줍니다.
    다른 예를 봅시다.상상해 보세요. 우리에게는 한 무리의 사람들이 있습니다. 그들의 나이와 이름, 우리는 색인을 가지고 있습니다. 이 결과를 되돌려줍니다.
    > Paginate(Match(Index("People_by_age_name")))
    
    {
      data: [
        [27, "Alex"],
        [33, "Abigail"],
        [39, "Adam"],
        [41, "Pier"],
        [50, "Anna"],
        [64, "Charles"]
      ]
    }
    
    만약 우리가 지금 30세에서 60세 사이의 모든 사람을 얻고 싶다면, 우리는 다음과 같은 조회를 실행할 수 있다.
    > Paginate(
      Range(
        Match(Index("People_by_age_name")),
        30, 60
      )
    )
    
    {
      data: [
        [33, "Abigail"],
        [39, "Adam"],
        [41, "Pier"],
        [50, "Anna"]
      ]
    }
    
    지금까지 줄곧 괜찮았다.
    만약 우리가 지금 이 결과들을 세분화하고 A와 B 사이의 이름을 얻고 싶다면?
    앞서 설명한 대로 Range()를 사용하여 이 문제를 해결할 수 없습니다.
    > Paginate(
      Range(
        Match(Index("People_by_age_name")),
        [30, "A"],
        [60, "B"]
      )
    )
    
    {
      data: [
        [33, "Abigail"],
        [39, "Adam"],
        [41, "Pier"],
        [50, "Anna"]
      ]
    }
    
    비록 문자열 "Pier"는 문자열 "B"뒤에 뚜렷하게 위치하지만, FaunaDB는 나이만 고려하여 [41, "Pier"]가 [60, "B"] 보다 낮은 상한선을 정합니다.

    범위, 그리고 필터링


    그렇다면 우리는 어떻게 해야만 진정으로 30~60대 사이의 모든 사람을 얻을 수 있고, 그들의 이름도'A'와'B'사이에 있을까?
    솔루션은 간단하게 Range()를 교체한 다음 FQL을 사용하여 필요한 모든 조건을 나타냅니다.
    > Paginate(
      Filter(
        Range(
          Match(Index("People_by_age_name")),
          [30],
          [60]
        ),
        Lambda(
          ["age", "name"],
          And(
            GTE(Var("name"), "A"),
            LTE(Var("name"), "B"),
          )
        )
      )
    )
    
    
    {
      data: [
        [33, "Abigail"],
        [39, "Adam"],
        [50, "Anna"]
      ]
    }
    
    여기에서 우리는 GTE() (크거나 같음) 과 LTE() (작거나 같음) 을 사용하여 명칭을 비교하고 이 두 조건이 And() 와true로 되돌아오는 것을 확보합니다.
    우리는 이 조회를 더욱 보완할 수 있다. 예를 들어 이름에'n'이나'i'가 있는 사람만 열거할 수 있다.
    > Paginate(
      Filter(
        Range(
          Match(Index("People_by_age_name")),
          [30],
          [60]
        ),
        Lambda(
          ["age", "name"],
          And(
            GTE(Var("name"), "A"),
            LTE(Var("name"), "B"),
            Or(
              ContainsStr(Var("name"), "n"),
              ContainsStr(Var("name"), "i")
            )
          )
        )
      )
    )
    
    {
      data: [
        [33, "Abigail"],
        [50, "Anna"]
      ]
    }
    
    문자열이 두 번째 매개 변수에 정의된 문자열을 포함하면 ContainsStr() 이 예에서 "n"또는 "i"로true를 되돌려줍니다.
    이 조건들은 매우 복잡할 수 있다. 왜냐하면 네가 그것들을 필요로 하기 때문이다. 우리는 정말 표면에 닿을 뿐이다.다음은 몇 가지 유용한 FQL 함수입니다. 값을 비교하고 조건을 표시하기 위해 이 함수를 확인해야 합니다.
  • And()
  • Any()
  • Or()
  • Equal()

  • GT()(보다 큼)

  • GTE()(크거나 같음)

  • LT()(소형)

  • LTE()(작거나 같음)
  • ContainsStr()
  • ContainsStrRegex()
  • ContainsValue()
  • 색인 및 범위


    지금까지 본고에서 우리는 집합의 모든 문서를 되돌려주는 색인만 사용하고 Range () 를 사용하여 이 결과를 필터링했습니다.물론, 우리는 용어가 있는 색인을 사용할 수 있다. 이 용어들은 필터 범위 전에 이미 많은 문서를 선택했다.
    새 컬렉션을 만듭니다.
    > CreateCollection({
      name: "RobotRepairs"
    })
    
    유형별로 필터링할 수 있는 인덱스와 Range()를 사용할 수 있는 필수 조건도 있습니다.
    > CreateIndex({
      name: "RobotRepairs_startTs_endTs_type_by_type",
      source: Collection("RobotRepairs"),
      values: [
        {field: ["data", "startTs"]},
        {field: ["data", "endTs"]},
        {field: ["data", "type"]},
        {field: ["ref"]}
      ],
      terms: [
        {field: ["data", "type"]}
      ]
    })
    
    이제 이러한 형식의 문서 두 개를 삽입합니다.
    > Create(
      Collection("RobotRepairs"),
      {
        data: {
          startTs: Time("2020-09-25T10:00:00Z"),
          endTs: Time("2020-09-27T18:00:00Z"),
          type: "CPU_REPLACE"
        }
      }
    )
    
    이 인덱스는 CPU\u REPLACE 필터링에서 반환된 결과입니다.
    > Paginate(
      Match(
        Index("RobotRepairs_startTs_endTs_type_by_type"),
        "CPU_REPLACE"
      )
    )
    
    {
      data: [
        [
          Time("2020-09-22T11:00:00Z"),
          Time("2020-09-23T13:00:00Z"),
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278203011981902355")
        ],
        [
          Time("2020-09-25T10:00:00Z"),
          Time("2020-09-27T18:00:00Z"),
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278203042867708435")
        ],
        [
          Time("2020-10-01T17:00:00Z"),
          Time("2020-10-01T19:00:00Z"),
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278202807195009555")
        ]
      ]
    }
    
    이제 수정 유형별로 필터링한 다음 Range()를 사용하여 두 시간 스탬프 사이에서만 수정을 완료할 수 있습니다.
    > Paginate(
      Range(
        Match(
          Index("RobotRepairs_startTs_endTs_type_by_type"),
          "CPU_REPLACE"
        ),
        [
          Time("2020-10-01T00:00:00Z"),
          Time("2020-10-01T00:00:00Z")
        ],
        [
          Time("2020-10-02T00:00:00Z"),
          Time("2020-10-02T00:00:00Z")
        ]
      )
    )
    
    {
      data: [
        [
          Time("2020-10-01T17:00:00Z"),
          Time("2020-10-01T19:00:00Z"),
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278202807195009555")
        ]
      ]
    }
    
    값이 있는 배열이 아닌 실제 문서를 가져오려면 맵 () 을 Lambda () 및 get () 과 함께 사용해야 합니다.
    > Map(
      Paginate(
        Range(
          Match(
            Index("RobotRepairs_startTs_endTs_type_by_type"),
            "CPU_REPLACE"
          ),
          [
            Time("2020-10-01T00:00:00Z"),
            Time("2020-10-01T00:00:00Z")
          ],
          [
            Time("2020-10-02T00:00:00Z"),
            Time("2020-10-02T00:00:00Z")
          ]
        )
      ),
      Lambda(
        ["startTs", "endTs", "type", "ref"],
        Get(Var("ref"))
      )
    )
    
    {
      data: [
        {
          ref: Ref(Collection("RobotRepairs"), "278202807195009555"),
          ts: 1601580160340000,
          data: {
            startTs: Time("2020-10-01T17:00:00Z"),
            endTs: Time("2020-10-01T19:00:00Z"),
            type: "CPU_REPLACE"
          }
        }
      ]
    }
    

    인덱스 바인딩 범위


    aprevious article에서 우리는 색인 귀속을 이해했다. 이것은 색인 결과에서 미리 계산한 값이다.
    특정 수정 유형의 바인딩을 사용하여 각 수정 기간을 반환하는 새 색인을 만듭니다.
    > CreateIndex({
      name: "RobotRepairs_duration_type_by_type",
      source: {
        collection: Collection("RobotRepairs"),
        fields: {
          durationMinutes: Query(
            Lambda("doc",
              TimeDiff(
                Select(["data", "startTs"], Var("doc")),
                Select(["data", "endTs"], Var("doc")),
                "minutes"
              )
            )
          )
        }
      },
      values: [
        {binding: "durationMinutes"},
        {field: ["data", "type"]},
        {field: ["ref"]}
      ],
      terms: [
        {field: ["data", "type"]}
      ]
    })
    
    이 인덱스는 기본적으로 반환됩니다.
    > Paginate(
      Match(
        Index("RobotRepairs_duration_type_by_type"),
        "CPU_REPLACE"
      )
    )
    
    {
      data: [
        [
          120,
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278202807195009555")
        ],
        [
          1560,
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278203011981902355")
        ],
        [
          3360,
          "CPU_REPLACE",
          Ref(Collection("RobotRepairs"), "278203042867708435")
        ]
      ]
    }
    
    이제 Range()를 사용하여 1 일 미만(또는 1440분) 수리를 수행할 수 있습니다.
    > Paginate(
      Range(
        Match(Index("RobotRepairs_duration_type_by_type"), "CPU_REPLACE"),
        [],
        [1440]
      )
    )
    
    {
      data: [
        [
           120,
           "CPU_REPLACE",
           Ref(Collection("RobotRepairs"), "278202807195009555")]
      ]
    }
    

    결론


    오늘은 여기까지.가치 있는 것을 배웠으면 좋겠어!
    질문이 있으면 언제든지 트위터로 연락 주세요.

    좋은 웹페이지 즐겨찾기