Iterate through a mongocxx query to get each key and value - mongo-cxx-driver

I am querying a collection with the following code:
bsoncxx::stdx::optional<bsoncxx::document::value> query_result =
collection.find_one(bsoncxx::builder::stream::document{} << "_tablename" << tableToSearch.toUtf8().constData() << "rowuuid" << UUIDToSearch.toUtf8().constData() << bsoncxx::builder::stream::finalize);
if(query_result)
{
}
I can see from the documentation how to print the result:
std::cout << bsoncxx::to_json(*maybe_result) << "\n";
But how can I Iterate through the result to get each key and its value as string?

Please have a read through the mongocxx and bsoncxx examples. You can find the example demonstrating cursor iteration here:
https://github.com/mongodb/mongo-cxx-driver/blob/fc9a44325e03bb8bb166e814caeb23413b4ba7af/examples/mongocxx/query.cpp#L43-L46
However, in your example you are doing a find one, so I guess you want to iterate each field, not each document. In that case, you can see examples of walking BSON objects here:
https://github.com/mongodb/mongo-cxx-driver/blob/fc9a44325e03bb8bb166e814caeb23413b4ba7af/examples/bsoncxx/view_and_value.cpp#L61-L62

Related

Converting string to csv

I have a piece of code in Ruby which essentially adds multiple lines into a csv through the use of
csv_out << listX
I have both a header that I supply in the **options and regular data.
And I am having a problem when I try to view the CSV, mainly that all the values are in one row and it looks to me that any software fails to recognize '\n' as a line separator.
Input example:
Make, Year, Mileage\n,Ford,2019,10000\nAudi, 2000, 100000
Output dimensions:
8x1 table
Desired dimensions:
3x3 table
Any idea of how to go around that? Either by replacing '\n' with something or using something else than csv.generate
csv = CSV.generate(encoding: 'UTF=8') do |csv_out|
csv_out << headers
data.each do |row|
csv_out << row.values
end
The problem seems to be the data.each part. Assuming that data holds the string you have posted, this loop is executed only once, and the string is written into a single row.
You have to loop over the indivdual pieces of data, for instance with
data.split("\n").each

How to iterate through an object and join one of it's attributes in a string?

I feel like there's a way to do the following code in ruby using just one line. Any takers?
arr = []
sample_object.all.each { |o| arr << o.id }
arr.join(', ')
This would return a string of id's for that object join by a ',' like:
"1, 2, 4, 5, 6, 8, 9"
You're right there is a simpler way; Use map or collect. Example using collect:
sample_object.all.collect(&:id).join(', ');
Reference: Enumerable
First there's no need to build arr, we could just write
sample_object.all.map { |o| o.id }.join(', ')
map allows us to covert an array of sample_objects to their ids returned by the block.
We can simplify that further using to_proc:
sample_object.all.map(&:id).join(', ')
I'm surprised to see no mention of pluck, which if you only want the id's of the objects would be an obvious contender since it's faster and less resource intensive than mapping/collecting across fully initialised objects.
sample_object.all.pluck(:id).join(', ')

Appium get xpath from element?

I have code which retrieves a static text element for me fine but what I want to do is then get the xpath of that element as a string. I'm using ruby. At this point I have an array of elements I have already retrieved. Below is what I've tried but no luck.
elements.each do |element|
if element.attribute("name").include? vProblem
p "Problem found, retrieving xpath..."
# Neither of these work
p "Problem xpath is: " + element.attribute("xpath").to_s
p "Problem xpath is: " + element.xpath.to_s
end
end
I don't believe there's an easy method or setting to call which will give you the xpath value. You would have to determine it yourself. To do this, iterate through all elements on the page until you found one that (A) matched the class of the element you're looking for and (B) matches the name/value of the element.
The only issue with this approach is that it assumes that the first element matching the class and value is the correct element. If there are multiple elements with the same class and value, it will only find the first.

String array in database. match and return values

I have the following data in a column letters in a mysql database. I saved them in varchar:
letters
["a","b"]
["a","b","d"]
["a","d"]
["d","c","e"]
["e","c","f"]
["c","f"]
["f","e"]
I am trying to match some elements. When I have params[:lttrs] as"a", I want to return:
["a","b"]
["a","b","d"]
["a","d"]
When I have params[:lttrs] as "c,e", I want to return:
["d","c","e"]
["e","c","f"]
My attempt is to retrieve all the rows and then match each of them with include?('a'), but with that, I can only do one element at a time. Is that the approach?
You can use the LIKE operator with wild card matching. This solution will be faster than using ruby. But it will be slow if you have a large table. If you provide more details about the reason for your data design we will be able to suggest alternative approaches.
like_params = params[:lttrs].split(",").map{|letter| "%#{letter}%"}
like = like_params.map{ "LIKE ?"}.join(" OR ")
Model.where(like, like_params)
You could try doing something like:
query = "letters "
r = 1
letters_arr = params[:lttrs].split(",")
letters_arr.each do |l|
if r == 1:
query << " like '%#{l}%'"
else
query << " or like '%#{l}%'"
end
end
letters_found = WhateverModel.where(query)
Obviously you need to make sure that the params are handled more safely than that, but that should get you on your way.

searching within an already retrieved mysql result

I'm trying to limit the number of times I do a mysql query, as this could end up being 2k+ queries just to accomplish a fairly small result.
I'm going through a CSV file, and I need to check that the format of the content in the csv matches the format the db expects, and sometimes I try to accomplish some basic clean-up (for example, I have one field that is a string, but is sometimes in the csv as jb2003-343, and I need to strip out the -343).
The first thing I do is get from the database the list of fields by name that I need to retrieve from the csv, then I get the index of those columns in the csv, then I go through each line in the csv and get each of the indexed columns
get_fields = BaseField.find_by_group(:all, :conditions=>['group IN (?)',params[:group_ids]])
csv = CSV.read(csv.path)
first_line=csv.first
first_line.split(',')
csv.each_with_index do |row|
if row==0
col_indexes=[]
csv_data=[]
get_fields.each do |col|
col_indexes << row.index(col.name)
end
else
csv_row=[]
col_indexes.each do |col|
#possibly check the value here against another mysql query but that's ugly
csv_row << row[col]
end
csv_data << csv_row
end
end
The problem is that when I'm adding the content of the csv_data for output, I no longer have any connection to the original get_fields query. Therefore, I can't seem to say 'does this match the type of data expected from the db'.
I could work my way back through the same process that got me down to that level, and make another query like this
get_cleanup = BaseField.find_by_csv_col_name(first_line[col])
if get_cleanup.format==row[col].is_a
csv_row << row[col]
else
# do some data clean-up
end
but as I mentioned, that could mean the get_cleanup is run 2000+ times.
instead of doing this, is there a way to search within the original get_fields result for the name, and then get the associated field?
I tried searching for 'search rails object', but kept getting back results about building search, not searching within an already existing object.
I know I can do array.search, but don't see anything in the object api about search.
Note: The code above may not be perfect, because I'm not running it yet, just wrote that off the top of my head, but hopefully it gives you the idea of what I'm going for.
When you populate your col_indexes array, rather than storing a single value, you can store a hash which includes index and the datatype.
get_fields.each do |col|
col_info = {:row_index = row.index(col.name), :name=>col.name :format=>col.format}
col_indexes << col_info
end
You can then access all your data in the for loop

Resources