How to search date ranges using ElasticSearch and Searchkick? - ruby

I'm using Rails 4.1.4 with searchkick (1.3.0) so I can use elastic search.
I have User model
class User
searchkick
def search_data
{
name: username,
email: email,
created_at: created_at.strftime("%d-%m-%Y")
}
end
end
created_at in dd-MM-yyyy format. How can I search for date range, let's say date from 01-01-2014 to 01-01-2015.
I tired something like User.search('*', where: {created_at: {gte:'01-01-2014', lte: '01-01-2015' } }) without getting the right results.
Any help?

class User
searchkick
def search_data
{
name: username,
email: email,
created_at: created_at.to_time
}
end
end
Instead of
created_at: created_at.strftime("%d-%m-%Y")
Try
created_at: created_at.to_time

I am not familiar with Searchkick, but if you use the elasticsearch gem, you can easily make a search request to ElasticSearch like
query = {
query: {
bool: {
must: [
{
term: {
username: "Kevin"
}
},
{
term: {
email: "email#gmail.com"
}
},
{
range: {
created_at: {
lte: "2016-06-06",
gte: "2016-06-06",
format: "yyyy-MM-dd"
}
}
}
]
}
}
}
The search request will look like:
client = Elasticsearch::Client.new
client.search(
index: index_name,
body: {
query: query
}
)
Hope this helps!

Form a proper DateTime object and your code should work
just use
.to_datetime

Related

How to dynamically access the names of fields being queries in a GraphQL resolver?

I have two collections:
dbPosts
id: mongoose.Schema.Types.ObjectId,
title: { type: String },
content: { type: String },
excerpt: { type: String },
slug: { type: String },
author: {
id: { type: String },
fname: { type: String },
lname: { type: String },
}
dbAuthors
id: mongoose.Schema.Types.ObjectId,
fname: { type: String },
lname: { type: String },
posts: [
id: { type: String },
title: { type: String }
]
I resolve my author queries as follows:
Query: {
authors: (parent, root, args, context) => {
return dbAuthor.find({});
},
author: (root, args, context) => {
return dbAuthor.findById(args.id);
},
},
Author: {
posts: (parent) => {
if(parent.posts) {
return parent.posts;
} else {
return dbAuthor.find({'author.id': parent.id});
}
},
}
The reason I'm resolving thus is to optimize my MongoDB requests by denormalizing my relationships. Here's the objective:
If you need just a list of authors with the titles of their works, all necessary fields are right there in dbAuthors, so no need to look up dbPosts. But if you need more details on each post returned, say, excerpts or slug, you look up dbPosts for the following condition:
{'author.id': parent.id}
But the problem is, if your query looks like this:
authors(id: "3") {
fname
lname
posts {
title
excerpt
}
}
it breaks, because there's no excerpt field returned in the parent object. This problem could be easily fixed if there were some way I could determine what fields are being queried on an author's posts field and then decide if the values returned in parent would suffice. If not, I could then proceed to look up dbPosts with the author's id value. Is it possible? Because if not, it would defeat the whole purpose of denormalizing your collections, something Mongo strongly urges you to do!
It's rather denormalized - data is duplicated ;)
You're probably looking for info.fieldNodes

Relation GraphQL

Trying to implement join but always getting null.
type User {
id: Int!
username: String!
recipes: [Recipe]
}
type Recipe {
id: Int!
title: String!
author: User
}
So basically i want to get data something like this:
User {
username,
recipes: [{//recipe}, {//recipe}]
}
And for Recipe i expecting
Recipe {
title,
author: {//user}
}
So i have query like below, and i want to get all recipes from database with included user
type Query {
recipes: [Recipe!]!
}
Here is my GraphiQL query
{
recipes {
id,
author {
id,
username
}
}
}
But in response i have author: null
{
"data": {
"recipes": [
{
"id": 1,
"author": null
}]
}
}
Any suggestions? Thanks!
Maybe somebody will face with similar issue.
Have fixed this. As said #Daniel Rearden in comments - yes issue was in resolver.
So you have to add this fields to resolver:
const resolverFunctions = {
User: {
recipes(author) {
return author.getRecipes();
}
},
Recipe: {
author(recipe) {
return recipe.getUser();
}
}
}
After you will get data what i needed above.

update elasticcache record without totally replacing it

I'm using this to add a bunch of records to the elasticcache index:
def self.index_trends(trend_hashes)
formatted_trends = trend_hashes.map do |trend_hash|
{
index: {
_index: 'trends',
_type: 'trend',
_id: trend_hash["id"],
data: trend_hash
}
}
end
elasticsearch.bulk({
body: formatted_trends
})
end
Now I need to update a record (given its id). I want to just add one key-val to the data hash, not replace the whole state. How can I do this using elasticsearch-ruby?
I dont know how to do this with ruby, but in ES there is update API.
Which look like this
POST test/type1/1/_update
{
"script" : "ctx._source.new_field = \"value_of_new_field\""
}
From example with ruby should be
client.update index: 'myindex', type: 'mytype', id: '1',
body: { script: 'ctx._source.tags += tag', params: { tag: 'x' } }

"OR" query in KeystoneJS Relationship Filters

Currently, all I see examples for is:
{
team: ':team'
}
But I need to be able to filter by multiple values ($or query)
Something like:
winner: {
type: Types.Relationship,
ref: 'Team',
filters: [
{
_id: ':homeTeam'
},
{
_id: ':awayTeam'
}
]
}
Is this possible?
Try the following code:
filters:{_id:{$in:[id_array]}}

How do I use More Like This API in Elasticsearch for ruby

I couldn't find any documentation about this at all. Or, maybe I'm missing something. I'm trying to use Elasticsearch's More Like This API with the elasticsearch gem.
I've indexed all documents already.
Here's my code:
require 'elasticsearch'
client = Elasticsearch::Client.new log: true
client.search index: 'movies', body: { query: { match: { description: 'test' } } }
client.search index: 'movies', body: { more_like_this: {
fields: ['description'],
like_text: 'Once upon a time'
} }
I'm getting this error:
Parse Failure [No parser for element [more_like_this]]];
}{[2fk_R7WbTky6UfMCbKPKGA][movies][1]
Try wrapping your more_like_this in query, like so:
client.search index: 'movies', body: {
query: {
more_like_this: {
fields: ['description'],
like_text: 'Once upon a time'
}
}
}
Hope this helps!

Resources