MongoDB has a data API, currently in Beta, but I am trying it out, since the MongoDB component is giving me so many issues in connecting.
I was able to make the Rest API work in Service Studio in test, but I'm having some troubles figuring out how to make it more flexible.
For the FIND endpoint, the call looks like this:
URL: https://data.mongodb-api.com/app/<Data API App ID>/endpoint/data/beta/action/find
Headers:
Content-Type: application/json
Access-Control-Request-Headers: *
api-key: <Data API Key>
Body:
{ "dataSource": "<cluster name>", "database": "learn-data-api", "collection": "people", "filter": { "name": "John Sample" }}
The problem is with the filter. Service Studio handles the one to one, name/values easily, but filter takes a collection. The filter is the query portion, and obviously you could query any undetermined number of fields. When I tried samples, Outsystems tried to build a rigid structure using the fields I was testing on as if those were the only fields I would ever test on. Basically, I need the insides of the collection to be flexible, like MongoDB.
Ideas?
Hi Joseph,
I thinks the simplest approach would be to create a structure with all the filters you want to use, and make sure that each attribute has their "Is Mandatory" and "Send Default Value" set to No. That way, the REST JSON that's send will only contain the attributes that are filled to filter on.
Hi Killian,
Thanks for the quick response. That's not really the answer I was hoping for, since it kind of takes away from the freedom of MongoDB to create any kind of Document. So, every time I create a new document type, I will need a new structure and a new method. No reuse. I'll try it anyway to be able to move forward with my proof of concept.
We really need to be able to create an element that will allow a structure with an internal list of undefined, 1 to many, name/value pairs. We are still talking about perfectly good JSON.
"Filter: { [name/value list] } "
If I could get the MongoDB component to connect, I wouldn't have to mess with this (working on that other angle, too).
I might work on my own MongoDB component, using the MongoDB API, because I really need a bulk upload method, which doesn't exist in the MongoDB component in the forge.
@Kilian Hekhuis , your solution does work, for the record. Even though this particular document has more elements than I care to count, I entered 16 of them, then set up a test page with only 3 of the elements. It works even if I only fill in one filter, proving that all the others were not sent in with blanks.
So, for this use case, I would need to create a method for every document I wanted to search, along with a structure that contains the possible fields in that document that I might want to search. So if I added a field to the document in MongoDB that I didn't care to search on, I wouldn't need to modify my method.
As far as reusability, if I had similar documents in different collections or databases, I could use the same method, since Collection and Database are two of the parameters. I might be able to use this.
Thanks again.
I don't know how MongoDB works, so I can't comment on needing a different method for each document. However, if my previous approach doesn't fulfil your requirements, you could also look at the ArdoJSON Forge component whether it allows to easily create JSON on the fly and just inject that JSON into the REST call. It'll be a bit more work though.
In general though, OutSystems works best with pre-defined data structures, as you'd typically want to present data on a Screen in a predictable manner. Too much flexibility could confuse the average user.
The basic challenge is that to query the database, you send name/value pairs for the fields in your WHERE clause. Could be one field or any combination of fields. The idea of a structure with all of the fields you might want to query is workable, but tedious. If you design a flexible search page with several possible, but optional, search fields, you basically do an IF for each field and only assign a value for the query if the user fills in a value for that field.