How to create a river using NEST client for ElasticSearch - rest

I'm beginning to work with Elastic Search on our MVC5 project.
We have continuous integration build in place, and would like to configure Elastic Search via NEST just like Entity Framework Code-First.
I'm struggling to find how I can invoke this request through NEST.
PUT _river/mytype/_meta
{
"type":"jdbc",
"jdbc": {
"driver":"com.microsoft.sqlserver.jdbc.SQLServerDriver",
"url" : "jdbc:sqlserver://127.0.0.1:1433;databaseName=MyDatabase;",
"user" : "user",
"password" : "password123",
"sql":"select * from RiverView",
"poll":"30s",
"index":"myindex",
"type": "mytype",
"strategy": "simple"
}
}
Does anyone have any idea how to do this?
Thank you in advance.

I was able to make this work with using ElasticClient.Raw
var client = CreateClient();
var river = new
{
type = "jdbc",
jdbc = new
{
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver",
url = String.Format("jdbc:sqlserver://{0}:1433;databaseName={1};", "127.0.0.1", "myDatabase"),
user = "user",
password = "password",
sql = "select * from mySqlView",
poll = "30s",
index = "index",
type = "type",
strategy = "simple"
}
};
string body = client.Serializer.Serialize(river, Formatting.Indented);
//HACK: Second parameter is a hack, appended _meta to type because NEST doesn't implement MetaPut()
var response = client.Raw.IndexPut("_river", "mytype/_meta", body);
Might not be the most elegant but worked for my requirement.

Related

How do I get all pages of a paginated response in a Power Query query that also uses parameters?

I'm trying to get all pages of the API responses using Power Query Editor for Power BI Desktop, but have run into some problems getting the query to run.
I've used This tutorial as a starting point (but am open to suggestions).
The Problem
Currently, when I invoke this function from the table with the ext_id, to, and from parameters, I get an Expression.Error that The parameter is expected to be of type Text.Type or Binary.Type.
All I want to do is get all the pages of the query. The pages are available in the response at reviews.page.total.
I'm also trying to be as efficient as possible, as AppFollow uses a credit-based "payment" system for transacting with the API. Can someone help figure out where I've gone wrong?
My Current Code
(ext_id as text, from as text, to as text) =>
let
BaseURL = "https://api.appfollow.io/api/v2/reviews?",
token = "[redacted]",
Query = "ext_id=" & ext_id & "&from=" & from & "&to=" & to,
GetJson = (Url) =>
let
Options = [Headers=[Accept="application/json", #"X-AppFollow-API-Token"= token ]],
RawData = Web.Contents(Url, Options),
Json = Json.Document(RawData)
in Json,
GetPageCount = () =>
let Url = BaseURL & Query,
response = GetJson(Url),
toJson = Json.Document(response),
total = toJson[reviews]{0}[page][total]
in total,
GetPage = (Index) =>
let
Page = "&page=" & (Index),
Url = BaseURL & Query & Page,
Json = GetJson(Url),
Value = Json[reviews]
in Value,
PageCount = GetPageCount(),
PageIndicies = {0..PageCount -1},
Pages = List.Transform(PageIndicies, each GetPage(_)),
Results = List.Union(Pages),
#"Converted to Table" = Table.FromRecords(Results)
in
#"Converted to Table"
Sample Response
{
"query": "/api/reviews?cid=[cid-here]&ext_id=[ext-id-here&from=2023-01-01&to=2023-01-31&host=global4.appfollow.io&method=GET&real_ip=xxx.xxx.xxx.xx",
"reviews": {
"list": [
{
"data": "[removed data]"
}
],
"total": 286,
"page": {
"current": 1,
"total": 3,
"next": 2,
"prev": null
},
"ext_id": "ext-id-here",
"store": "as"
}
}
Error Message
Expression.Error: The parameter is expected to be of type Text.Type or Binary.Type.
Details:
query=/api/reviews?ext_id=[ext-id-here]&to=2023-01-31&from=2023-01-01&dev103=1&cid=[cid-here]&host=global4.appfollow.io&method=GET&real_ip=xxx.xx.xxx.xxx
reviews=[Record]
Try
Page = "&page=" & Text.From((Index)),

Strapi : populate result from a relation collection

I'm using strapi 3.4.4 with mongodb.
I've got a location collection with a reservation linked collection (a location can have many reservations).
Location Model
text field : title of the location
Reservations Model
linked collection : has one author
My goal is to populate the author name when I made a get request to /location
But right now, my request is :
{
"reservations": [
{
"_id": "60be41626a15ab675c91f417",
"author": "60be3d40ea289028ccbd4d5a",
"id": "60be41626a15ab675c91f417"
}
],
"_id": "60be40a26a15ab675c91f414",
"title": "New York Plaza",
},
As you can see, the author is an id, so I try to edit location/controllers/location.js to
const { sanitizeEntity } = require('strapi-utils');
module.exports = {
/**
* Retrieve records.
*
* #return {Array}
*/
async find(ctx) {
let entities;
if (ctx.query._q) {
entities = await strapi.services.location.search(ctx.query);
} else {
entities = await strapi.services.location.find(ctx.query, ['reservations', 'reservations.author']);
}
return entities.map(entity => sanitizeEntity(entity, { model: strapi.models.location }));
},
};
I followed this guide : https://www.youtube.com/watch?v=VBNjCgUokLk&list=PL7Q0DQYATmvhlHxHqfKHsr-zFls2mIVTi&index=27
After further research, it seems that the syntax ['reservations', 'reservations.author'] doesn't work to populate with mongodb.
await strapi.services.post.find(ctx.query, {path:'reservations', populate:{path:'author'}});
works
You need to provide the API key you're using "Full access" for what ever reason, "Read only" won't return relations.
On top of that you will still need to use the query parameter populate.
http://localhost:1337/api/locations?populate=*

Grails 2.4.4 Map of Objects example not being persisted to Mongo DB

I was following Grails 2.4.4 documentation to make a Map of Objects, but my objects were not being persisted to Mongo DB. So, I decided to make a sanity check using the exactly same example provided by the documentation and it also did not work.
Steps:
grails create-app test
Next, I included the mongo plugin to my BuilConfig.groovy :
compile ":mongodb:3.0.3"
//runtime ":hibernate4:4.3.6.1"
Then, I configured my DataSource.groovy:
environments {
production {
grails {
mongo {
replicaSet = [ "xxxxxxxx"]
username = "xxxx"
password= "xxxxxxxxxxxxxx"
databaseName = "xxxxxx"
}
}
}
development {
grails {
mongo {
replicaSet = [ "xxxxxxxx"]
username = "xxxx"
password= "xxxxxxxxxxxxxx"
databaseName = "xxxxxx"
}
}
}
test {
grails {
mongo {
replicaSet = [ "xxxxxxxx"]
username = "xxxx"
password= "xxxxxxxxxxxxxx"
databaseName = "xxxxxx"
}
}
}
}
Here is my Book domain class:
package test
class Book {
String name
Map authors
static hasMany = [authors:Author]
static constraints = {
}
}
And here is my Author domain class:
package test
class Author {
String name
static constraints = {
}
}
using the grails console, I ran the following script :
import test.*
def a = new Author(name:"Stephen King")
def book = new Book(name:"test")
book.authors = ["stephen":a]
book.save(failOnError:true)
And then, I took a look at my Mongo DB and I could not find the map that was supposed to be persisted.
{
"_id": 1,
"name": "test",
"version": 0
}
I really appreciate if you have any clues of what is going on or if you know any workaround to persist a Mapin Grails.
Thanks
Here you go. Add the following to your Book domain class:
static embedded = ["authors"]
On the second thought, why are you using a Map instead of List for authors?
Since this is a MongoDB database, it will save all the fields of Author.

How to append a key:value to a MongoDB cursor?

Is it possible to append a key:value to a MongoDB cursor?
I tried this:
cursor = collection.find(query,projection)
cursor['my_message'] = "value here" # trying to add key:value here
But it doesn't seem to work (500).
In more context, this works:
dbname = 'my_db'
db = connection[dbname]
collection = db.my_collection
query = {'key_1': my_var}
projection = {'key_2':1}
cursor = collection.find(query,projection)
response.content_type = 'application/json'
return dumps(cursor)
This doesn't:
dbname = 'my_db'
db = connection[dbname]
collection = db.my_collection
query = {'key_1': my_var}
projection = {'key_2':1}
cursor = collection.find(query,projection)
cursor['my_message'] = "value here" # trying to add key:value here
response.content_type = 'application/json'
return dumps(cursor)
Edit: And just to visualise what is being returned successfully (without the appended value), it is something like:
[{ document_1 },{ document_2 },{ document_3 }]
And I expect it to look something like:
["my_message":"value here",{ document_1 },{ document_2 },{ document_3 }]
Edit: I tried the following as an alternative and also got a 500.
entries = []
cursor = collection.find(query,projection)
for entry in cursor:
entries.append(entry)
entries['my_message'] = "value here"
response.content_type = 'application/json'
return dumps(entries)
Really, WiredPrarie answered this for you right at the beginning, and everyone is saying the same thing.
We know what you want to do. You want your serialized response to be sent back with some information you want to put in and then the resultset. I also presume that you want to use these results and your other data, likely loaded into some JavaScript processing store.
I have never seen anything that didn't expect some sort of structure like:
{
"result": "ok",
"meta": [{ akey: "avalue"}, {bkey: "bvalue"}],
"results:[ // this is your 'entries' value here
{ document_1 },
{ document_2 },
{ document_3 },
....
So what everyone is saying is embed your entries into another structure that you are going to serialize and return. By trying to push your other keys into the entries list you are doing it the wrong way around.

Using HATEOAS and Backbone.js

I've started experimenting with Backbone.js, and was struck by the documentation for the documentation for the url property on Backbone.Model.
In particular, I'm building out a REST API that uses HATEOAS/hypermedia to drive the client(s).
I can see the usefulness of Backbone's default behaviour of building up URLs itself for items in a collection, but for my case, would prefer to have the model URLs built out of the data that is parsed.
Has anyone extended/built on Backbone to make it do this? Maybe building upon a "standard" like HAL?
EDIT:
For clarification, let's say I have the following:
GET /orders >>
[
{
"_links": {
"self": "/orders/123"
}
"name": "Order #123",
"date": "2012/02/23"
},
{
"_links": {
"self": "/orders/6666"
}
"name": "Order #666",
"date": "2012/03/01"
},
]
and I have an Order model like:
var Order = Backbone.Model.extend({
});
I would like the url property to be automatically pulled out of the "self" reference in the HAL. I think creating a new base model something like (not tested):
var HalModel = Backbone.Model.extend({
url: function() {
return get("_links").self;
},
});
Thoughts?
I've extended backbone to do exactly this, the library is available here:
https://github.com/mikekelly/backbone.hal
Thanks for the clarification #Pete.
I think I see what your proposing and I suppose it could work. However, in your example, you first had to know the /Orders url before you were able to get the orders. And if you reworked your json to have an id property, you'd be pretty close to the default implementation of backbone.
Now if you just want to use a generic model or base model (e.g. HALModel) and just bootstrap it with data, your approach could be useful and definitely could work. However, I would look at overriding parse to pull the url out and set it on the model:
parse: function(response) {
this.url = response._links.self;
delete response._links;
return response;
}
I complement here the response of Simon to explain how to easily do it using gomoob/backbone.hateoas.
// Instanciation of an Hal.Model object is done the same way as you're
// used to with a standard Backbone model
var user = new Hal.Model({
firstName: "John",
lastName: "Doe",
_links: {
avatar: {
href: "http://localhost/api/users/1/avatar.png"
},
self: {
href: "http://localhost/api/users/1"
}
},
_embedded: {
address: {
"city" : "Paris",
"country" : "France",
"street" : "142 Rue de Rivoli",
"zip" : "75001",
"_links" : {
"self" : {
"href" : "http://localhost/api/addresses/1"
}
}
}
}
});
// Now we you can easily get links, those lines are equivalent
var link1 = user.getLink('avatar');
var link2 = user.getLinks().get('avatar');
// So getting self link is simple too
var self = user.getLink('self');
// All the Hal.Link objects returned by backbone.hateoas are in fact
// standard Backbone models so its standard Backbone
link1.get('href');
link1.getHref();
// You can do more with shortcut methods if your HAL links
// have more properties
link1.get('deprecation');
link1.getDeprecation();
link1.get('name');
link1.getName();
link1.get('hreflang');
link1.getHreflang();
link1.get('profile');
link1.getProfile();
link1.get('title');
link1.getTitle();
link1.get('type');
link1.getType();
linke1.get('templated');
link1.isTemplated();
// You can also manipulate embedded resources if you need
user.getEmbedded('address').get('city');
user.getEmbedded('address').getLink('self');
...
Finally we provide an Hal.Model.url() implementation which is more powerful than standard Backbone url() and which is very useful if you use HAL.
// By default url() returns the href of the self link if this self
// link is present
user.url();
// If the self link is not defined then url() has the same behavior
// as standard Backbone url() method
// My user is link to a user collection having a URL equal to
// 'http://localhost/user1'
user.url(); // http://localhost/users/1
// My user is not link to a user collection in this case the URL is
// generate using the model urlRoot property by default
user.urlRoot = 'http://myserver/users';
user.url(); // http://localhost/users/1
// backbone.hateoas also allows you to define an application wide root
// URL which prevent to use absolute URLs everywhere in your code
Hal.urlRoot = 'http://localhost/api'; // HAL root API URL
var user = new Hal.Model({ id : 1});
user.urlMiddle = 'users';
user.url(); // http://localhost/api/users/1
Hope this helps, don't hesitate to post issues on our github if you need help on this.
You can override the url function on the model to calculate the URL however you want; it's completely extensible.