Add built-in function omit keys from an object

add a built-in function called Omit. What it does is return the object back BUT removes specified keys,

So if you have:

Get(
  Match(
    Index("userByEmail"),
    "user@email.com"
  )
)

Which returned:

{
  // ... other meta values
  data: {
    email: "user@email.com",
    name: "Juan Dela Cruz",
    hashedPassword: "asdasd12312radgadgvadfasfr12esa" // pretend it's a hashed string :)
  }
}

Applying the omit function like so:

Omit(
  ["hashedPassword"],
  Select(
    ["data"],
    Get(
      Match(
        Index("userByEmail"),
        "user@email.com"
      )
    )
  )
);

Should return

{
  email: "user@email.com",
  name: "Juan Dela Cruz"
}

furthermore, the first argument can accept a 2d array, like so:

Omit(
  [
    ["data", "hashedPassword"] // remove the data.hashedPassword from the object
  ],
  Get(
    Match(
      Index("userByEmail"),
      "user@email.com"
    )
  )
);

Resulting to the following:

{
  // ... other meta values
  data: {
    email: "user@email.com",
    name: "Juan Dela Cruz"
  }
}

So to summarize, the function would be:

Omit(paths, fromObject)

  • Paths: Array of paths to the keys to be omitted.
  • fromObject: Target object to derive the result from.

Omit must be a pure function, that is, it doesn’t mutate the fromObject parameter, so you can do:

Let(
  {
    result: Select(
      ["data"],
      Get(
        Match(
          Index("userByEmail"),
          "user@email.com"
        )
      )
    ),
    removedResult: Omit(
      [
        ["data", "hashedPassword"] // remove the data.hashedPassword from the object
      ],
      Var("result")
    )
  },
  // rest of the code
)

and Var("result") should still be the original object prior to Omit call.

Current work around that I found:

Unsure if there’s a better approach than this

Let(
  {
    result: Get(Match(Index("userByEmail"), "user@email.com")),
    filteredData: Merge(
      Select(["data"], Var("result")),
      {
        hashedPassword: null // this removes the hashedPassword from the result
      }
    )
  },
  Merge(
    Var("result"),
    {
      data: Var("filteredData")
    }
  )
)

which will return the same result as:

Omit(
  [
    ["data", "hashedPassword"]
  ],
  Get(Match(Index("userByEmail"), "user@email.com"))
)

Which will be this (from the example given above):

{
  // ... other meta values
  data: {
    email: "user@email.com",
    name: "Juan Dela Cruz"
  }
}

Hi @aprilmintacpineda,

You can also try this way.
If you have a document which looks like this:

Create(Collection('test'),{data:{val1:1,val2:2,val3:3,val4:4,val5:5,val6:6,val7:7,val8:8,val9:9,val10:10}})
{ ref: Ref(Collection("test"), "283968229559239173"),
  ts: 1607072057266000,
  data:
   { val1: 1,
     val2: 2,
     val3: 3,
     val4: 4,
     val5: 5,
     val6: 6,
     val7: 7,
     val8: 8,
     val9: 9,
     val10: 10 } }

and you want to omit some fields, you can do this way:

Let(
  {
    fieldsToOmit: ["val4","val5","val6","val9"],
    doc: Select(['data'],Get(Ref(Collection("test"), "283968229559239173"))),
    cleanedDoc: Reduce(Lambda(['acc','value'],Merge(Var('acc'),ToObject([[Var('value'),null]]))), Var('doc'),Var('fieldsToOmit'))
  },
  Var('cleanedDoc')
)

of course, you can replace the doc value with something more generic or even write a function and reuse the code.

In the meantime, I will file an FR for that function.

Luigi

2 Likes

Thanks @aprilmintacpineda for posting this request. I definitely see the benefit in providing an explicit omit function which would allow you to more easily filter out unneeded fields. The current methods for filtering out unneeded fields are very verbose and not easy to read. At present we are working on a new FQL language specification which will greatly reduce the complexity of the query language and expand expressability. We will factor your request for an omit function into the design of the language.

3 Likes