Document structure -
{
"_id" : "b3bf7422-4993-4728-ae6f-98f35aa52a9c",
"feed_user_type" : "user",
"relation" : "reported_by",
"notification_title" : "Thank you for submitting the report. The moderators will now review the evidence.",
"notification_type" : {
"email" : false,
"feed" : false,
"notification" : true
},
"updated_at" : ISODate("2016-12-01T12:14:41.269Z"),
"created_at" : ISODate("2016-12-01T12:14:41.269Z")
}
Following queries works fine
Userfeed.where(:notification_type.feed => true).offset(offset).limit(size).asc(:created_at)
Userfeed.where(:feed_user_type => "user").offset(offset).limit(size).asc(:created_at)
First query is querying the field in the hash and second one is simple query querying a normal field and gives proper results.
But i combine both the queries i don't get any results at all. I tried following two syntax for combining the above query clause
userfeeds = Userfeed.where(:notification_type.feed => true,:feed_user_type => current_user.id).offset(offset).limit(size).asc(:created_at)
userfeeds = Userfeed.where(:notification_type.feed => true).where(:feed_user_type => current_user.id).offset(offset).limit(size).asc(:created_at)
How can i combine a hash field query clause with normal field query clause?
Thanks
This should work:
all_of(:'notification_type.feed' => true,:feed_user_type => current_user.id)
Related
I need to parse URLs and store unique Pages. Thanks to sites like Youtube which build unique pages based on query parameters (and not just on the URI path portion), I need to discriminate on the full url, not just the path part. (I'm ignoring the fragment section for now, I don't think this will be useful for my application)
Here's a sample of the data I'm working with
{
"url": "https://www.youtube.com/watch?v=0jExdUIc49s?&ab_channel=PokerStaples",
"decoded": {
"scheme": "https",
"host": {
"prefix": "www",
"suffix": "youtube.com"
},
"path": "watch",
"queries": [
{
"query": "v",
"value": "0jExdUIc49s?"
},
{
"query": "ab_channel",
"value": "PokerStaples"
}
]
},
}
Step 1
Build a query like this, but dynamic based on the queries from the supplied URL.
p = Page.joins(:page_queries)
.where(path: 'watch', domain: #domain)
.where(page_queries: {query: 'v', value: '0jExdUIc49s?'})
.first_or_create
PageQueries is as you'd expect, Page has_many PageQueries (attributes page_id, query, value)
I think I'm getting close by creating a hash, but obviously I'm missing something:
pq = { 'v':'0jExdUIc49s?' }
p = Page.joins(:page_queries)
.where(path: 'watch', domain: #domain)
.where(page_queries: pq)
.first_or_create
Here's the output:
p = Page.joins(:page_queries).where(path: 'watch', domain:
#domain).where(page_queries: pq) Page Load (1.4ms) SELECT
"pages".* FROM "pages" INNER JOIN "page_queries" ON
"page_queries"."page_id" = "pages"."id" WHERE "pages"."path" = ? AND
"pages"."domain_id" = 162 AND "page_queries"."v" = ? [["path",
"watch"], ["v", "0jExdUIc49s?"]]
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column:
page_queries.v: SELECT "pages".* FROM "pages" INNER JOIN
"page_queries" ON "page_queries"."page_id" = "pages"."id" WHERE
"pages"."path" = ? AND "pages"."domain_id" = 162 AND
"page_queries"."v" = ?
Any ideas?
I've been banging my head against this problem for hours. Your help is GREATLY appreciated.
Step 2
Each Domain record also has_many Discriminators - those queries which discriminate a unique result. (IE, utm_ queries are used for tracking and of no use in this application). We add these in as we find domains which require query values to define a unique page.
For YouTube like we've been using, "v" is the important parameter, though for my testing, I added a second one.
I pull them into an array:
#domain.discriminators.pluck(:query)
[
[0] "v",
[1] "test"
]
..and then the goal is to use the merge of the "discriminators" and the supplied queries to create and use only unique Page records with useful categories.
I haven't got this far yet, but once I get past step 1 I don't think it will be much of a problem.
Thanks!
Per request - The basic schema & relations
Domain
has_many :pages
has_many :discriminators
t.string "suffix"
t.string "prefix"
t.string "connection"
Discriminator
belongs_to :domain
t.string "query"
t.integer "domain_id"
Page
belongs_to :domain
has_many :page_queries
t.string "path"
t.integer "domain_id"
PageQuery
belongs_to :page
t.string "query"
t.string "value"
t.integer "page_id"
Now, the fugly way to (almost) solve my problem! I really hope someone can come up with some ninja Ruby to save me from this fate. (I'm not writing this in as an answer because I can't in good conscience call this an answer. It's ducktape.)
#url = "https://www.youtube.com/watch?v=0jExdUIc49s?&ab_channel=PokerStaples"
uri = URI(#url)
#queries = uri.query.split('&')
#pq = {}
#queries.each do |q|
k = q.split('=').first
v = q.split('=').last
#pq.store(k.to_sym, v)
end
#request = "Page.joins(:page_queries).where(path: 'watch', domain: #domain)"
#pq.each {|q, v| #request << ".where(page_queries: {query: '#{q}', value:'#{v}'})"}
eval(#request)
Fugly! Here's hoping for something more elegant.
I know it's bad to search in serialize, but I encounter this problem.
I got a model called Question and contain a serialize column assignments
id question_set_id assignments
1 1 {"12982": true, "12332": true}
2 2 {"12222": true, "12332": true}
3 3 {'11111': true}
And I got a array called group_ids
group_ids = ["12982","12332"]
I need to find the record who contain at least one group_id in assignments.
So, the result of this example should be like
[
{
:id => 1,
:question_set_id => 1,
:assignments => {"12982": true, "12332": true}
},
{
:id => 2,
:question_set_id => 2,
:assignments => {"12222": true, "12332": true}
}
]
I've tried
Question.where("assignments IS NOT NULL").where("assignments LIKE '%?%'", 12982)
It seems works, but how to apply an array?
And according this answer, I tried
Question.where("assignments IS NOT NULL").where("assignments= ?", groups_ids.to_yaml)
However, it return a blank array.
With mysql 5.7.? you can query JSON data directly. I didn't try it but following the docs something like
Question.where("JSON_CONTAINS_PATH(assignments , 'one', '$[*].assignments.12982', '$[*].assignments.12332') == 1")
should work. You can furthor more convert your column from text to JSON data type and get validation of the json document and optimized storage.
I have a mongo-backed contact database in rails. I am doing reports that reports multiple checkbox using a filter.
For example:
I am using checkbox filter
Table name is Conversion
Columns in Conversion table are: browser, date, city, state, country, network, language
I am selecting date, city for filter, after filtering grouping should occur, based on the filter
Note: first filter next only grouping
Sometimes: date, city, country for filter, it will depends on the user
I have done this code only
Conversion.collection.aggregate([
{ "$match" => {
"date" => { '$gte' => start_date, '$lte' => end_date }
}
},
{ "$group" => {
"_id" => {
"country" => "$country",
"city" => "$city",
"browser" => "$browser",
"network" => "$network",
"language" => "$language"
}
}
},
])
But this code is grouping all columns every time. I want the checkbox selected column only grouping to occur. For that how do I write the grouping code? Can anyone suggest any idea?
Using the elastsearch-rails gem, currently I have:
response = Employee.search(
size: 20,
query: {
multi_match: {
"query" => search_terms,
"type" => "cross_fields",
"fields" => ["first_name^3", "last_name^3", "full_name^4", "email", "job_description^5", "job_title^5"]
}
}
)
What I notice is that by doing the multi-match / cross_fields search, if I search for a term that appears only once in an Employee database column (e.g., "John" would only appear in first_name, not job_description or job_title), then I get no results back. If a term, (say a job title like "lawyer" appears in more than 1 field such as job_description and job_title), I get results back. Why is this? This seems counter-intuitive.
Using Elasticsearch with Rails 3 and tire gem.
I have got facets to work on a couple of fields, but I now have a special requirement and not sure it is possible.
I have two fields on my model Project that both store the same values: Country1 and Country2
The user is allowed to store up to two countries for a project. The drop down menus on both are the same. Neither field is required.
What I would like is a single facet that 'merges' the values from Country1 and Country2 and would handle clicking on those facets intelligently (i.e. would find it whether it was in 1 or 2)
Here's my model so far: (note Country1/2 can be multiple words)
class Project < ActiveRecord::Base
mapping do
indexes :id
indexes :title, :boost => 100
indexes :subtitle
indexes :country1, :type => 'string', :index => 'not_analyzed'
indexes :country2, :type => 'string', :index => 'not_analyzed'
end
def self.search(params)
tire.search(load: true, page: params[:page], per_page: 10) do
query do
boolean do
must { string params[:query], default_operator: "AND" } if params[:query].present?
must { term :country1, params[:country] } if params[:country].present?
end
end
sort { by :display_type, "desc" }
facet "country" do
terms :country1
end
end
end
Any tips greatly appreciated!
This commit https://github.com/karmi/tire/commit/730813f in Tire brings support for aggregating over multiple fields in the "terms" facet.
The interface is:
Tire.search('articles-test') do
query { string 'foo' }
# Pass fields as an array, not string
facet('multi') { terms ['bar', 'baz'] }
end
according to the elasticsearch docs for the terms facet http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html this should be possible:
Multi Fields:
The term facet can be executed against more than one field, returning
the aggregation result across those fields. For example:
{
"query" : {
"match_all" : { }
},
"facets" : {
"tag" : {
"terms" : {
"fields" : ["tag1", "tag2"],
"size" : 10
}
}
}
}
did you try providing an array of fields to the term facet like terms :country1, :country2 ?
This seems to work but I need to test it more: facet('country') { terms fields: [:country1, :country2]}