replacing a value in a json array with sinatra - ruby

I have records with a 'resource' field which can contain multiple resources. When I return this data, I need to iterate over this field and return an individual record for each value in the field. I am currently using sinatra and am able to interate over the fields okay, but I am having difficulty replacing the field in the json array.
For example
event: Name
resources: resourceA, resourceB, resourceC
This record needs to be returned as 3 uniqe records/events with only one resource per record.
With the code listed below, I am getting three records, but all three records are coming back with the same resource value (resourceC)
Here is my code
docs = #db.view('lab/events', :startkey => params[:startDate], :endkey => endSearch)['rows']
rows = Array.new
docs.each do |doc|
resources = doc['value']['resources'].split(",")
resources.each do |r|
doc['value']['resources'] = r
rows.push(doc['value'])
end
end
Any help is greatly appreciated.
Thanks
Chris

if you use the ruby gem "json" you can convert the json string to a hash
require 'json'
converted_hash = JSON(json_string).to_hash
This should be much easier to manage.
You can then turn the hash to a JSON string:
new_json_string = converted_hash.to_json

Basically what is happening is ruby is seeing all three records as the same record so as the hash value is updated on one record, it impacts all other records that were created from the same doc. To get around this, I acutally needed to create a duplicate record each time through and modify it's value.
docs = #db.view('lab/events', :startkey => params[:startDate], :endkey => endSearch)['rows']
rows = Array.new
docs.each do |doc|
resources = doc['value']['resources'].split(",")
resources.each do |r|
newDoc = doc['value'].dup # <= create a duplicate record and update the value
newDoc["resources"] = r
rows.push(newDoc)
end
end

Related

Put the sample results in an array, a hash, etc using ruby and oci8

I use ruby-2.3 and oci-8 gem. I want to make the select query:
stm = "select * from DATASERVICEUSERS t where boss<>100 and loginad is not null"
res = CONN.exec(stm).fetch_hash do |row|
#do something with row
end
CONN.logoff
How can I query the result of the whole to put for example in an array or hash, instead of cycle pass through each record? I need just a collection of elements of the result of this request.
Oci-8 doesn't provice that. The .exec method produces a cursor that you you need to process like your code demonstrates. You can fill up an array with an array of fields or a hash.
Here an example for an array
records = []
conn.exec(sql) { |record| records << record}
# records: [["xxxx", "xxxx"], ["yyyy", "yyyy"], ..]
I know this is quite an old question but I've come across this problem. I'm not as well versed in ruby but oci8 2.2.7 actually provides fetch_hash
https://www.rubydoc.info/gems/ruby-oci8/OCI8/Cursor#fetch_hash-instance_method
here's an example from my use case:
records = []
dataCursor = #odb.exec(queryUUNRData)
while((data = dataCursor.fetch_hash) != nil)
records.push data
end
dataCursor.close
the resulting dataset already includes the column names as hash key

Mongoid "find" returns nil, when "find_by" retrieves record

I'm using Mongoid to access a MongoDB database, however I'm running into an odd problem. It seems like I can only query for records using find_by, as find will always return nil:
invoices = Invoice.find({})
p "invoices"
p invoices
puts ''
invoice = Invoice.find_by({ _id: <ObjectId> })
p "invoice"
p invoice
puts ''
The second query using find_by will return a single record. According to the documentation, find should be returning every record that satisfies the query.
Does anyone have an idea what could be causing this?
Be careful not to confuse the Moped syntax with the Mongoid syntax. For Mongoid, the docs describe the find method:
Find a document or multiple documents by their ids. Will raise an error by default if any of the ids do not match
If you really want every record, Invoice.all can do the trick. (Also be careful with your find_by method. The Mongoid syntax varies from mongo's a bit, so you don't have to have the curlies around your params.)

How to retrieve the field name of a ShapeFile feature field?

I am using gdal-ruby to parse ESRI ShapeFiles like in this demo. I want to iterate through all features in order to push the field values into a database. However, I cannot find out how to retrieve the name of each field which I need to match the database column. By now I can only work with the field index of the field such as:
dataset = Gdal::Ogr.open(filename)
number_of_layers = dataset.get_layer_count
number_of_layers.times do |layer_index|
layer = dataset.get_layer(layer_index)
layer.get_feature_count.times do |feature_index|
feature = layer.get_feature(feature_index)
feature.get_field_count.times do |field_index|
field_value = feature.get_field(field_index)
# How can I find out the name of the field?
puts "Value = #{field_value} for unknown field name"
end
end
end
I checked the available methods with irb and looked into the API documentation. It seems as if I am searching for the wrong terms.
Looking at the OGR API itself, I think you need to go via feature.GetDefnRef, to get the feature definition, then .GetFieldDefn for the relevant field, and finally .GetNameRef...?
...
feature.get_field_count.times do |field_index|
defn_ref = feature.get_defn_ref
field_defn = defn_ref.get_field_defn(field_index)
field_name = field_defn.get_name
field_value = feature.get_field(field_index)
puts "Value = #{field_value} for field named #{field_name}"
end
...
ds = ogr.Open(filename, 1)
layer = ds.GetLayer()
for i in range(len(layer.schema)):
print(layer.schema[i].name)

Ruby check if record exist in mongodb

Just simple check with ruby driver if record exist in database.
Like
Main = db.collection(main)
Record = main.find("record" => name)
If record?
Puts record exist
Else
Dont exist
End
This doesnt work can someone tell me how to do it
The following will put true or false whether the record exists
puts main.record.where(record: name).exists?
This can be done with the collection method "find" as you did, but the selector must be a hash.
col = db.collection(main)
record = col.find({:property => value})
Find also accepts an optional hash of options.
Take a look at the documentation. http://api.mongodb.org/ruby/current/Mongo/Collection.html#find-instance_method

Ruby datajob with mongoid

I'm trying to use ruby and mongoid in order to extract some data from an oracle database and into my mongoDB in order to perfom a couple of operations on it.
The question is:
I created my 'Record' class with includes the Mongoid::Document and set up all my fields, and have already assigned the data coming out of the oracle database, and have all my BSON objects stored in an array.
Now my question is: How I save them?
Here's my piece of code
query = db.report # Sequel Object
query.each do |row|
r = Record.new #Mongoid class
r.directory_name = row[:directory_name]
r.directory_code = row[:directory_id]
r.directory_edition = row[:edition]
r.last_updated = row[:updated]
r.canvass = row[:canvass_id]
r.specialty_item = row[:item]
r.production_number = row[:prodnr]
r.status = row[:exposure_status]
r.scanned_date = row[:scandate]
r.customer_id = row[:customer_id]
r.sales_rep = row[:sales_rep_name]
r.phone = row[:phone]
r.customer_name = row[:customer_name]
records << r
end
You would need to do Record.collection.insert(records). Although note that this will skip any validations you have written in your Mongoid model but will be a little faster than creating mongoid records and saving them, as it will use the ruby mongo driver directly. You should only do this if you know that data is consistent.
If you want to do all the validations on your data before saving them in MongoDB, you should create a model instead of putting them in an array.
So you can persist the data extracted in MongoDB in three ways according to your preferences:
Insert all records at once using mongo driver, but beware the array you are creating can be huge:
query.each do |row|
.....
end
Record.collection.insert(records)
Insert one record at a time using mongo driver(replace records << r with new line)
query.each do |row|
.....
Record.collection.insert(r)
end
Insert one record at a time using Mongoid and all the validations and callbacks(replace records << r with new line)
query.each do |row|
.....
r.save
end
update: Missed that you are already creating the record hence the mongo driver suggestions. If you want to use mongo driver directly, you should use a hash instead of Mongoid model. i.e instead of
r = Record.new
r.status = row[:status]
# copy more data
you should do
r = {}
r[:status] = row[:status]
# copy more data

Resources