Search by first item of nest field List<object> in elasticsearch - elasticsearch

How can i search by first item of nest field type List in elasticsearch?
public class Data
{
public int Id{get;set;}
public string Name{get;set;}
public List<History> Logs{get;set;}
}
public class History
{
public byte Status { get; set; }
public string Note { get; set; }
public DateTime DateProcessed { get; set; }
}
Example, i have 3 records like as:
PUT /my_index/Data/1
{
"name": "name 1",
"logs": [
{
"status": "2",
"note": "processed",
"dateProcessed": "2016-04-11"
},
{
"status": "1",
"note": "new",
"dateProcessed": "2016-04-10"
}
]
}
PUT /my_index/Data/2
{
"name": "name 2",
"logs": [
{
"status": "1",
"note": "new",
"dateProcessed": "2016-04-11"
}
]
}
PUT /my_index/Data/3
{
"name": "name 2",
"logs": [
{
"status": "3",
"note": "error",
"dateProcessed": "2016-04-11"
},
{
"status": "1",
"note": "new",
"dateProcessed": "2016-04-10"
}
]
}
Now, i want to get records which have first item of list (field logs) with status equal 1.
In above example, result is second record.
Please help me, thank you!

You can you Script Query, but that would be very slow.
{
"filter": {
"script": {
"script": "_source.logs?.first()?.status.equals('1')"
}
}
}
Make sure to enable scripting

The way you should go seems like Nested Query.
You should define your list as Nested during mapping. Then you can write Nested Queries on them and filter your "Data" depending on inner hits of "History".

Related

Get GraphQL output without second curly bracket

I have a problem. I do not want a "break" down in my GraphQL output. I have a GraphQL schema with a person. That person can have one or more interests. But unfortunately I only get a breakdown
What I mean by breakdown is the second curly brackets.
{
...
{
...
}
}
Is there an option to get the id of the person plus the id of the interests and the status without the second curly bracket?
GraphQL schema
Person
└── Interest
Query
query {
model {
allPersons{
id
name
interest {
id
status
}
}
}
}
[OUT]
{
"data": {
"model": {
"allPersons": [
{
"id": "01",
"name": "Max",
"interest ": {
"id": 4488448
"status": "active"
}
},
{
"id": "02",
"name": "Sophie",
"interest ": {
"id": 15445
"status": "deactivated"
}
},
What I want
{
{
"id": "01",
"id-interest": 4488448
"status": "active"
},
{
"id": "02",
"name": "Sophie",
"id-interest": 15445
"status": "deactivated"
},
}
What I tried but that deliver me the same result
fragment InterestTask on Interest {
id
status
}
query {
model {
allPersons{
id
interest {
...InterestTask
}
}
}
}

How to mutate a list of objects in an array as an argument in GraphQL completely

I cannot mutate a list of objects completely, because only the last element of the array will be mutated.
What already works perfectly is, if I put each element ({play_positions_id: ...}) in the array manually like here:
mutation CreateProfile {
__typename
create_profiles_item(data: {status: "draft", play_positions: [{play_positions_id: {id: "1"}}, {play_positions_id: {id: "2"}}]}) {
id
status
play_positions {
play_positions_id {
abbreviation
name
}
}
}
}
Output:
{
"data": {
"__typename": "Mutation",
"create_profiles_item": {
"id": "1337",
"status": "draft",
"play_positions": [
{
"play_positions_id": {
"id": "1",
"abbreviation": "RWB",
"name": "Right Wingback"
}
},
{
"play_positions_id": {
"id": "2",
"abbreviation": "CAM",
"name": "Central Attacking Midfielder"
}
}
],
}
}
}
Since you can add many of those elements, I defined a variable/argument like here
mutation CreateProfile2($cpppi: [create_profiles_play_positions_input]) {
__typename
create_profiles_item(data: {status: "draft", play_positions: $cpppi}) {
id
status
play_positions {
play_positions_id {
id
abbreviation
name
}
}
}
}
Variable object for above:
"cpppi": {
"play_positions_id": {
"id": "1"
},
"play_positions_id": {
"id": "2
}
}
Output:
{
"data": {
"__typename": "Mutation",
"create_profiles_item": {
"id": "1338",
"play_positions": [
{
"play_positions_id": {
"id": "2",
"abbreviation": "CAM",
"name": "Central Attacking Midfielder"
}
}
],
}
}
}
Schema:
input create_profiles_input {
id: ID
status: String!
play_positions: [create_profiles_play_positions_input]
}
input create_profiles_play_positions_input {
id: ID
play_positions_id: create_play_positions_input
}
input create_play_positions_input {
id: ID
abbreviation: String
name: String
}
At the last both snippets, only the last object with the id "2" will be mutated. I need these to use the defined input type from my backend.
I figured it out. I got it wrong with the brackets in the variable. Here the solution:
"cpppi": [
{
"play_positions_id": {
"id": "1"
}
},
{
"play_positions_id": {
"id": "2"
}
}
]

How to filter GraphQL query?

I'm new to GraphQL and got stuck in a query. Well, this is sample GQL that returns every record in database:
{
viewer {
savingsAccount {
id
feed {
id
__typename
title
detail
postDate
... on TransferInEvent {
amount
originAccount {
name
}
}
... on TransferOutEvent {
amount
destinationAccount {
name
}
}
... on TransferOutReversalEvent {
amount
}
... on BillPaymentEvent {
amount
}
... on DebitPurchaseEvent {
amount
}
... on BarcodePaymentEvent {
amount
}
... on DebitWithdrawalFeeEvent {
amount
}
... on DebitWithdrawalEvent {
amount
}
}
}
}
}
Here is sample return:
{
"data": {
"viewer": {
"savingsAccount": {
"id": "5c8fe258-34fd-4bdc-bfb6-761bc78435df",
"feed": [{
"id": "5fcd6040-cf19-4dbf-be25-47d2f1a7a29b",
"__typename": "DebitPurchaseEvent",
"title": "Test",
"detail": "Test $$",
"postDate": "2020-12-06",
"amount": 59.7
}, {
"id": "5fcd5bbd-fc70-4d87-944d-d0a186559289",
"__typename": "DebitPurchaseEvent",
"title": "Test",
"detail": "Test $$",
"postDate": "2020-12-06",
"amount": 30.0
}
}
}
}
}
How do I apply filter to return some specific postDate? I mean, after, before, etc. This attribute is stored as string but I believe it is possible to do some convertion.
Thanks in advance!

ASP.NET Core Web API Swagger docs incorrect with reference loop between classes

I have the following classes in my application:
public class Person
{
public int Id { get; set; }
public Guid PublicKey { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual List<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public DateTime Date { get; set; }
public virtual Person Person { get; set; }
public int PersonId { get; set; }
}
and the following API controller that just gets a list of all the people (there are always 2, and they always have 3 orders each):
[Route("api/[controller]")]
public class PeopleController : Controller
{
// GET api/people
[HttpGet]
public List<Person> Get()
{
PeopleService people = new PeopleService();
return people.GetAllPeople();
}
}
I should point out that I had issues from the start with the navigation property on the Order class referring back to the Person that owns it, as the Json.NET formatter doesn't like this out of the box and you have to configure it to ignore reference loops. I have done this in the Startup.cs like so:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(o =>
{
o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.None;
o.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
services.AddSwaggerGen();
}
This works great, and when I make a request I get the following response:
[
{
"orders": [
{
"id": 1,
"date": "2016-10-26T17:16:35.21",
"personId": 1
},
{
"id": 2,
"date": "2016-10-26T17:16:35.21",
"personId": 1
}
],
"id": 1,
"publicKey": "b6a7c21c-86d8-4bb9-9a05-bd394e6ed0c9",
"firstName": "Lauren",
"lastName": "Phillips"
},
{
"orders": [
{
"id": 3,
"date": "2016-10-26T17:16:35.21",
"personId": 2
},
{
"id": 4,
"date": "2016-10-26T17:16:35.21",
"personId": 2
}
],
"id": 2,
"publicKey": "8b5a90b4-a9a2-4a0e-96dd-529962972456",
"firstName": "Robert",
"lastName": "West"
}
]
I am using Swashbuckle to generate Swagger docs for my API. The "Example Value" that is generated by Swashbuckle/Swagger seems to be including the Person again within each order:
[
{
"id": 0,
"publicKey": "string",
"firstName": "string",
"lastName": "string",
"orders": [
{
"id": 0,
"date": "2016-10-27T14:19:52.437Z",
"person": {
"id": 0,
"publicKey": "string",
"firstName": "string",
"lastName": "string",
"orders": [
{}
]
},
"personId": 0
}
]
}
]
I don't want people consuming the API to expect the person to be included again in each order, especially as that isn't what you actually get because I configured it to ignore reference loops above. I imagine that this issue is related to the reference loop, but I am not sure. Does anyone know how to fix this?
Probably, you can use the attribute - [JsonIgnore] to not show that up in the swagger documentation

WebAPI 2 Odata Filter not working

I have a problem with using multiple filters on my WebAPI 2 Odata project.
We only want JSON output and only have one object type to query so we set the url to "/" without the possibility to use a different controller.
I have an object I want to query with the following properties:
public class Content
{
public int Id { get; set; }
public string Title { get; set; }
public string Excerpt { get; set; }
public string Link { get; set; }
public IList<Tag> Tags { get; set; }
}
public class Tag
{
public string Id { get; set; }
public string Name { get; set; }
}
And the controller code looks like this:
public class ContentController : ApiController
{
private readonly IContentRepository _repository;
// constructor
public ContentController(IContentRepository repository)
{
_repository = repository;
}
[Queryable]
public IQueryable<Content> Index()
{
// IContentRepository.GetAll returns an IEnumerable List of Content
return _repository.GetAll().AsQueryable();
}
}
Now, I've mocked some testdata with adding multiple objects to the repository that have multiple tags with values set to either (test1, test2 or test3). Now when i Query
http://localhost:xxx?$filter=Tags/any(o: o/Id eq 'test1')
I get all objects with Tag/Id set to 'test1'. But if I query
http://localhost:xxx?$filter=Tags/any(o: o/Id eq 'test1' and o/Id eq 'test2')
I get no result (JSON return = []). But it should return objects that have both tags.
What am I doing wrong?
EDIT:
My sample data JSON looks like this:
[
{
"Id": 1,
"Title": "TESTOBJECT 1",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test1",
"Name": "Test Tag 1",
}
],
},
{
"Id": 2,
"Title": "TESTOBJECT 2",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test2",
"Name": "Test Tag 2",
}
],
},
{
"Id": 3,
"Title": "TESTOBJECT 3",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test3",
"Name": "Test Tag 3",
}
],
},
{
"Id": 4,
"Title": "TESTOBJECT 4",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test1",
"Name": "Test Tag 1",
},
{
"Id": "test2",
"Name": "Test Tag 2",
}
],
},
{
"Id": 5,
"Title": "TESTOBJECT 5",
"Excerpt": "",
"Link": "",
"Tags": [
{
"Id": "test1",
"Name": "Test Tag 1",
}
],
}
]
Now query one gives me object 1,4,5 and I would expect query two to give me object 4. How can I accomplish this with odata?
Did you want this?
http://localhost:xxx?$filter=Tags/any(o: o/Id eq 'test1') and Tags/any(o: o/Id eq 'test2')
((X == "test1") AND (X == "test2")) will always return false!
If you want to identify Tags whose property Id is test1 or test2, use the or operator.

Resources