When retrieving results from ES using Chewy, the date-typed results are returned as Ruby strings.
My index is defined just like:
class OrdersIndex < Chewy::Index
define_type Order do
field :id, type: "keyword"
field :created_at, type: "date"
end
end
When the results are retrieved:
OrdersIndex.order(created_at: :desc).first.created_at.class
# => String
Is there a way to deserialize this date field in a Ruby date object automatically, without having to explicitly map the results using Time#parse?
How to update only :share_count, maybe this should be done with upsert ?
I use ruby on rails and mongoid
class FeedEntry
include Mongoid::Document
require 'social_shares'
field :name, type: String
field :url, type: String
field :share_count, type: Integer
before_save :load_shares
def load_shares
self.share_count = SocialShares.total url, %w(sharedcount)
end
def self.update_shares_today
#feed_entries = FeedEntry.today.all
#feed_entries.each do |feed_entry|
feed_entry.update
end
end
end
count = SocialShares.total url, %w(sharedcount)
update_attributes share_count: count
This is probably an issue on my part I have been struggling through some Rails and mongo samples to get up to speed (This is all for learning not for work.) This current project I get a JSON string from a api and I put that in mongo. So changing the document structure is not really an option. I then have been trying to map that into a Rails model so I can use the data.
The JSON is a report that contains many transactions that contain many LogLines.
Snippet from a doc
< Report _id: 583 c3baac0baf90a7ee26f6e,
ReportName: "PtSomIntPerfThreeLevelTest-1480341940187",
TestName: "PtSomIntPerfThreeLevelTest",
Transactions: [{
"colId" => "50437d6c-49c1",
"InfoPlate" => "[0SXdokPL-R13VQZwi]",
"rowId" => "1",
"sortDate" => 1480341975952,
"transactionType" => "REQUEST",
"description" => "description text for my document",
"startDate" => "11/28/2016 14:06:15",
"startDateMS" => 1480341975952,
"endDate" => "11/28/2016 14:06:23",
"endDateMS" => 1480341983069,
"finalEndDate" => "11/28/2016 14:06:23",
"finalEndDateMS" => 1480341983069,
"completeDuration" => "7 seconds",
"completeDurationMS" => 7117,
"feedProcessingDuration" => "7 seconds",
"feedProcessingDurationMS" => 7117,
"logLines" => [{
"id" => "1062b1ca-0f04",
"timestamp" => 1480341975952,
"transactionType" => "REQUEST",
"transactionStep" => "RECEIVE",
"collationId" => "50437d6c-49c1-438a-9b8",
"runName" => "runName-1480341940187",
"msg" => "Import default",
"elapsedSeconds" => "0.0",
"elapsedMS" => 0,
"InfoPlate" => "[0SXdokPL-3rmxW3oH]"
},
I have a report model, and a transaction model ( I will do LogLines after doing 1 at a time) My report model does fine I can get a single report doc based on an ID and it returns the report. I can then do a "report.transactions" and get a json blob of the transactions (almost always multiple transactions in a report) BUT its not recognized as a transaction model (will post all code below) So I cannot say transaction.InfoPlate I get a no such method error. I have relationships in my model but I also have a " field :Transactions, type: Array" which in looking at the rails cast on mongoid is not in theres. Without that I get nothing so the relationship "embeds_many :transactions" does not allow me to get a report.transaction. Sorry if that is confusing my Rails lingo is low. Short and sweat I want to get a report then get the transactions and be able to do transactions.ColID and get the col ID .
My goal is to get a model for each part of the document report, transaction, LogLines. I do not seem to understand how to do that.
Report Model (Works Fine)
class Report
include Mongoid::Document
field :ReportName, type: String
field :TestName, type: String
field :Transactions, type: Array
field :ReportDurationMS, type: String
embeds_many :transactions
end
Transaction Model
class Transaction
include Mongoid::Document
field :colId, type: String
field :InfoPlate, type: String
field :rowId, type: String
field :sortDate, type: String
field :transactionDate, type: String
field :description, type: String
field :startDate, type: String
field :startDateMS, type: Integer
field :endDate, type: String
field :endDateMS, type: Integer
field :finalEndDate, type: String
field :completeDuration, type: String
field :completeDurationMS, type: Integer
field :feedProcessingDuration, type: String
field :feedProcessingDurationMS, type: Integer
field :logLines, type: Array
embedded_in :report, :inverse_of => :transactions
end
Report Controller (Index Method) Debug logger is just there while I hack around
def index
#reports = Report.all
Rails.logger.info("********* #{#reports.inspect} ***********")
end
Transaction Controller (This is what I can't get to return a transaction as a model) I get a transaction back from #report.transactions but its just a string of json as opposed to a ruby model. Or at least I can't call anything like #transaction.colId. Just returns no such method. Transactions is an array there are many so I did try transactions.first.InfoPlate but still to me it seems Rails just seems the transaction that comes back as a string of JSON not an object.?
class TransactionsController < ApplicationController
before_action :set_transaction, only: [:show, :edit, :update, :destroy]
def index
#report = Report.find(params[:report_id])
#transaction = #report.transactions
Rails.logger.info("********* report #{#report.inspect} ***********")
#transactions = #report.transactions
Rails.logger.info("********* transaction #{#transactions.inspect} ***********")
end
My route
resources :reports do
resources :transactions
end
The above post made me go back in and match all my case and that seems to be working.
Everyone! I have a model:
class Model
include Mongoid::Document
field :price1, :type =>Integer
field :price2, :type =>Integer
field :price3, :type =>Integer <== I want this field to be always result of price1 + price2
end
My question is: How can I make :price3 to be always autofilled by sum of price1 + price2.
Thank you very much for help!
You want to use the callbacks interface. There are various callbacks exposed such as:
require "mongoid"
require "pp"
Mongoid.configure.connect_to("test")
class Model
include Mongoid::Document
field :price1, type: Integer
field :price2, type: Integer
field :price3, type: Integer
store_in collection: "mymodel"
before_save do |document|
document.price3 = document.price1 + document.price2
end
end
model = Model.new
model.price1 = 2
model.price2 = 3
model.save
Which results in the "price3" field being set to the sum of the other two values.
I have a model like this:
class Invoice
include Mongoid::Document
field :local, type: String
field :date, type: DateTime
field :total, type: Float
end
class LogInvoice
include Mongoid::Document
field :date, type: Date
field :local, type: String
field :summary, type: Hash
end
The field summary is a Hash like this:
summary = {invoices : 0, amount : 0.0}
For each invoice stored, I must create an LogInvoice for that day with total number of Invoice (count of Invoice) in LogInvoice.summary[:invoices] and with the total ammount of money (summatory of Invoice.total) in LogInvoice.summary[:amount]
If the Invoice exist I must to update the LogInvoice of that day.
I can't know if a object existe because LogInvoice.find() returns an exception if it doesn't, so how can I update an existing object LogInvoice or created if it doesn't?
Thank you
If I've understood your question you should do something like this:
my_invoice_criteria = Invoice.all # or Invoice.where date: the_date_I_want or anything else
my_invoice_criteria.each do |invoice|
log_invoice = LogInvoice.find_or_create_by date: invoice.obtain_proper_date
#Use this for atomic persistence
log_invoice.inc :"summary.invoices" => 1
log_invoice.inc :"summary.amount" => invoice.total
#Use this for standard persistence
log_invoice.summary[:invoices]+=1
log_invoice.summary[:amount]+=invoice.total
log_invoice.save
end
Ref:
Atomic persistence Docs
Standard persistence Docs