Potential bug with Merge inside Map of Events

Hello, I"m trying to Map a Merge operation inside a Events result :

Map(
Select("data",Paginate(Events(Match(Index("by_cat"), "cat1")))),
Lambda("X", Merge( Var("X") , {other: 1}) )
)

This gives me this error :

Error: [
  {
    "position": [
      "map",
      "expr",
      "merge"
    ],
    "code": "invalid argument",
    "description": "Object expected, Object provided."
  }
]

The error is quite strange, it says I’m using Object instead of…well: objects :smiley:

I tried to make sure I have Objects indeed :


Map(
Select("data",Paginate(Events(Match(Index("by_cat"), "cat1")))),
Lambda("X", IsObject( Var("X")) )
)

which returns :

[true, true, true, true]

Here is my index, nothing too fancy :

{
  name: "by_cat",
  unique: false,
  serialized: true,
  source: "col1",
  terms: [
    {
      field: ["data", "cat"]
    }
  ]
}

Hi @MaximeWeyl and welcome! :wave:

Thanks for bringing this to our attention. "Object expected, Object provided." is not a great error message!

Merge and other functions that expect Objects as input expect plain ole objects. Events are not treated as plain objects here. Unfortunately, it looks like the error handling is interpreting an Event as an "Object" when it’s building the message.

It is not clear if Events should or should not be treated as plain objects for the purposes of functions like Merge. And in either case, the error message is unhelpful. I’ve created an internal ticket to straighten this out.

Workarounds

you can define your own Object to return like this:

Map(
  Paginate(Events(Match(Index("by_cat"), "cat1"))),
  Lambda("event", {
    ref: Select("ref", Var("event")),
    ts: Select("ts", Var("event")),
    action: Select("action", Var("event")),
    data: Select("data", Var("event"))    

    other: 1
    // ...
  })
)

In general, I recommend handling pagination in your application, rather than doing Select("data",..., but that can be a matter of preference for you and your application.

1 Like

Just a minor followup, but the Select("data", Paginate(...) is unnecessary. Paginate returns a page, which is an array that contains optional before and after cursor values. Selecting the data field from a Paginate result just gives you the array information that Map would operate on anyway.

There’s no real harm to using Select this way, but it does contribute to the billed compute ops. Removing it saves you 1/50th of a compute op!

1 Like

Thank you for the explaination !

Could you provide an example ? I do not know how to get the results of a Match(Index(…)) without using FQL Paginate()

Thank you !
I thought that Events were only objects with a “data, before, after” schema, I did not know that Map could iterate them.

This is a Page, so not necessarily tied to being a Page of Events. When you use the Paginate function, this is the result that is always returned. Functions like Filter, Map, and Reduce can accept a Page as an argument, and they will act on the array of data contained in the Page.

(If you are familiar with functional programming, you might consider a Page to be like a kind of monad – roughly speaking, a wrapper around the data that abstracts away some of the functionality of working with it)

Sorry, I didn’t mean to imply not to use Paginate. What I meant is what @ewan said: you don’t have to Select("data", SOME_PAGE) because you can pass the Page directly into Map. The biggest reason I recommend it, though, is because if you Select("data",... then your client will not receive the before or after cursors, which are needed for getting additional Pages. The example I provided does not use Select, so I was offering an example of returning the pagination cursors. Doing so mean that your application needs to be aware it is receiving a page, not just the data, though.

1 Like

Thank you, thats clear to me.
Have a nice day :slight_smile:

2 Likes