Query on a nested field using elastic4s on ElasticSearch - elasticsearch

I want to query a nested document that is indexed in ES.
For example, the nested field is user which contains two fields id and name. I want to query all documents where the name exactly matches the field user.name.
Cannot figure out how to use the elastic4s DSL for that.

This is how you do nested queries in elastic4s:
First of all, setting up the index such that you have a nested type:
client.execute {
create index "nested" mappings {
"show" as {
"actor" typed NestedType
}
}
}
Then with some sample data
client.execute(
index into "nested/show" fields(
"name" -> "game of thrones",
"actor" -> Seq(
Map("name" -> "peter dinklage", "birthplace" -> "Morristown"),
Map("name" -> "pedro pascal", "birthplace" -> "Santiago")
)
)
)
Then the key part. To search, you used the nested (or in elastic4s 1.4 beta, nestedQuery) to "drop into" the nested scope, where you can search using any standard query type. Here I am just using a simple termQuery search.
client.execute {
search in "nested/show" query nested("actor").query(termQuery("actor.name" -> "dinklage"))
}

How about:
clientProvider.getClient.execute {
(search in path)
.query(
nested("[something].user").query(
bool(must(
term("something.user.name" -> name)
))
)
)
}
Since I'm not familiar with your structure i will provide my own example and maybe you could go from there:
venueData consist of meta data about a venue and the venue itself.
venue got a list of employees that is a NestedType nested()
employee got an id that is of type Long
def venueByEmployeeId(employeeId: Long): Future[Option[VenueData]] = {
clientProvider.getClient.execute {
(search in path)
.query(
nested("venue.employees").query(
bool(must(
term("venue.employees.id" -> employeeId)
))
)
)
}.map(_.getHits.jsonToList[VenueData].headOption)
}
The thing I did forget about the query is that you need to write the entire path term("venue.employees.id" -> employeeId)

Related

Contentful GraphQL filter with relational queries and reference fields

I'm currently trying to filter entries with a field references, many.
In other words, the field takes multiple locations with each locations consisting of city among other fields.
For my query I want to get every entry that has a location with a specific city name set.
The following query filters an entry that takes only on reference for location, how would it look like when having many?
export const NEWS_ARTICLES = gql`
query GetNewsArticles($location: String) {
entryCollection(
where: {
location: { city: $location }
}
) {
items {
location
}
}
}
`;
Pulling GraphQL's schema all I get is locationCollection_exists - is this even possible?
I found the following article, which seems to do what I desire, but for the Filter API and not GraphQL: https://www.contentful.com/developers/docs/concepts/relational-queries/
Contentful DevRel here. 👋
Filtering by a linked collection entry is not supported right now. What you can do though it flip the query around.
export const NEWS_ARTICLES = gql`
query GetNewsArticles($location: String) {
cityCollection(
# your filter
) {
items {
linkedFrom {
# all the entries linking to this entry
}
}
}
}
`;
You can find more information about this approach in the docs or this blogpost.

How to sort on nested field in graphql ruby?

How do I sort on a nested field (or a virtual attribute) in graphql-ruby?
ExampleType = GraphQL::ObjectType.define do
name 'Example'
description '...'
field :nested_field, NestedType, 'some nested field' do
// some result that is virtually calculated and returns
OpenStruct.new(a: 123//some random number, b: 'some string')
end
end
QueryType = GraphQL::ObjectType.define do
name 'query'
field: example, ExampleType do
resolve -> (_obj, args,_ctx) {
Example.find(args['id']) //Example is an active record
}
end
field: examples, types[ExampleType] do
resolve -> (_obj, args,_ctx) {
// NOTE: How to order by nested field here?
Example.where(args['id'])
}
end
end
And if I am trying to get a list of examples ordered by nested_field.a:
query getExamples {
examples(ids: ["1","2"], order: 'nested_field.a desc') {
nested_field {
a
}
}
}
You can not order Active record by virtual attribute, because Active record can not match this virtual attribute to SQL/NoSQL query. You can avoid limitation, by creating view at DB layer. In GraphQL, sorting/pagination should be implemented at DB layer. Without that sorting/pagination implementation queries all data from DB to application memory.
Also, I want to recommend you switching from order argument with string type to sort argument with [SearchSort!] type based on enums. GraphQL schema will looks like that:
input SearchSort {
sorting: Sorting!
order: Order = DESC
}
enum Sorting {
FieldName1
FieldName2
}
enum Order {
DESC
ASC
}
It helps you implement mapping from GraphQL subquery to DataBase query.

Spring data mongo db count nested objects with a specific condition

I have a document like that:
'subject' : {
'name' :"...."
'facebookPosts':[
{
date:"14/02/2017 20:20:03" , // it is a string
text:"facebook post text here",
other stuff here
}
]
}
and I want to count the facebookPosts within a specific objects that their date field contains e.g "23/07/2016".
Now, I do that by extracting all the documents and count in the client side (spring ) , But I think that's not efficient.
You need to aggregate your results.
final Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(Criteria.where("facebookPosts.date").regex(REGEX)),
Aggregation.unwind("facebookPosts"),
Aggregation.group().count().as("count"));
Regex might not be the best solution, just an example.
unwind will split array into separate elements you can then count.
Create a class that will hold the count, something like:
public class PostCount {
private Long count;
// getters, setters
}
And then execute it like this:
AggregationResults<PostCount> postCount = mongoTemplate.aggregate(aggregation, Subject.class, PostCount.class);
long count = postCount.getMappedResults().get(0).getCount();

elastic4s - control the analyzer to use in term query

I want to control the analyzer in my search query.
At the moment my code looks like this:
client.execute(search in indexName / documentType query {
bool {
must(
termQuery("email", email),
termQuery("name", name)
)
}
}
How can I control the analyzer here?
Note that a term query does not analyze the search terms, so what you're looking for is probably a match query instead and it would go like this:
client.execute(search in indexName / documentType query {
bool {
must(
termQuery("email", email),
matchQuery("name", name) <--- change this to match query
.analyzer(StandardAnalyzer) <--- add this line
)
}
}
The test cases are a good source of information as well. In the SearchDslTest.scala file you'll find how to set all possible properties of a match query.

Search Query in RavenDB

I would like to know the Search Query for the below condition. I have created an index called MeetingEventIndex as below:
public class MeetingEventIndex : AbstractIndexCreationTask<mngtMeetingEvent>
{
public MeetingEventIndex ()
{
Map = docs => from d in docs select new {d.meetingroomid, d.text, d.details};
Index(x=>x.meetingroomid, FieldIndexing.Analyzed);
Index(x=>x.text, FieldIndexing.Analyzed);
Index(x=>x.details, FieldIndexing.Analyzed);
}
}
I am trying to create a search query as below "Search the term in text or details field and meetingroomid==123"
docsession.Query<mngtMeetingEvent, MeetingEventIndex>()
.Search(x=>x.text , search)
.Search(x=>x.details, search. options: SearchOptions.Or)
.Search(x=>x.meetingroomid, "123", option.SearchOptions.And)
.ToList()
But this is not returning any result.
Basically I am looking for ((searchterm in text field || searchterm in details field ) and mrcode in meetingroomid field).
Please help.
Your query is probably more easily expressed as LuceneQuery, instead:
docsession.Advanced..LuceneQuery<mngtMeetingEvent, MeetingEventIndex>()
.OpenSubClause()
.Search("text", search)
.OrElse()
.Search("details", search)
.CloseSubClause()
.AndAlso()
.WhereEquals("meetingroomid", "123")
.ToList();

Resources