How to make a multiline string value from MongoDB's bson.M in Golang? - mongodb

I'm creating a telegram bot using Golang, and I need some advice on how to retrieve a multiline string value from function in Golang, that has same logic like this Python string
answer = """1 John 95
2 Sam 89
3 Mike 72"""
I have a function that creates a MongoDB request that gets me a data in bson.M datatype. And after that I need to send this queried data to a user as a single string value using this form:
msg := tgbotapi.NewMessage(
update.Message.Chat_ID,
answer,
)
bot.Send(msg)
I don't really know how to transform this bson.M data into a single multiline string.
bson.M response that I get from the function:
[map[_id:ObjectID("62a4acf2a494a2814238c6e1") bandMember:John name:School12 points:95]
map[_id:ObjectID("62a4acf2a494a2814238c6e2") bandMember:Sam name:School15 points:89]
map[_id:ObjectID("62a4acf2a494a2814238c6e3") bandMember:Mike name:School7 points:72]]
And I have to insert it in a string variable of "answer" (see above example)
Thanks in advance!

Loop through the documents and sprintf a line for each document. Join the lines with newline to get the final result.
var lines []string
for i, m := range data {
lines = append(lines, fmt.Sprintf("%d %s %d", i+1, m["bandMember"], m["points"]))
}
result := strings.Join(lines, "\n")

Related

Converting numbers into timestamps (inserting colons at specific places)

I'm using AutoHotkey for this as the code is the most understandable to me. So I have a document with numbers and text, for example like this
120344 text text text
234000 text text
and the desired output is
12:03:44 text text text
23:40:00 text text
I'm sure StrReplace can be used to insert the colons in, but I'm not sure how to specify the position of the colons or ask AHK to 'find' specific strings of 6 digit numbers. Before, I would have highlighted the text I want to apply StrReplace to and then press a hotkey, but I was wondering if there is a more efficient way to do this that doesn't need my interaction. Even just pointing to the relevant functions I would need to look into to do this would be helpful! Thanks so much, I'm still very new to programming.
hfontanez's answer was very helpful in figuring out that for this problem, I had to use a loop and substring function. I'm sure there are much less messy ways to write this code, but this is the final version of what worked for my purposes:
Loop, read, C:\[location of input file]
{
{ If A_LoopReadLine = ;
Continue ; this part is to ignore the blank lines in the file
}
{
one := A_LoopReadLine
x := SubStr(one, 1, 2)
y := SubStr(one, 3, 2)
z := SubStr(one, 5)
two := x . ":" . y . ":" . z
FileAppend, %two%`r`n, C:\[location of output file]
}
}
return
Assuming that the "timestamp" component is always 6 characters long and always at the beginning of the string, this solution should work just fine.
String test = "012345 test test test";
test = test.substring(0, 2) + ":" + test.substring(2, 4) + ":" + test.substring(4, test.length());
This outputs 01:23:45 test test test
Why? Because you are temporarily creating a String object that it's two characters long and then you insert the colon before taking the next pair. Lastly, you append the rest of the String and assign it to whichever String variable you want. Remember, the substring method doesn't modify the String object you are calling the method on. This method returns a "new" String object. Therefore, the variable test is unmodified until the assignment operation kicks in at the end.
Alternatively, you can use a StringBuilder and append each component like this:
StringBuilder sbuff = new StringBuilder();
sbuff.append(test.substring(0,2));
sbuff.append(":");
sbuff.append(test.substring(2,4));
sbuff.append(":");
sbuff.append(test.substring(4,test.length()));
test = sbuff.toString();
You could also use a "fancy" loop to do this, but I think for something this simple, looping is just overkill. Oh, I almost forgot, this should work with both of your test strings because after the last colon insert, the code takes the substring from index position 4 all the way to the end of the string indiscriminately.

How do I parse out a number from this returned XML string in python?

I have the following string:
{\"Id\":\"135\",\"Type\":0}
The number in the Id field will vary, but will always be an integer with no comma separator. I'm not sure how to get just that value from that string given that it's string data type and not real "XML". I was toying with the replace() function, but the special characters are making it more complex than it seems it needs to be.
is there a way to convert that to XML or something that I can reference the Id value directly?
Maybe use a regular expression, e.g.
import re
txt = "{\"Id\":\"135\",\"Type\":0}"
x = re.search('"Id":"([0-9]+)"', txt)
if x:
print(x.group(1))
gives
135
It is assumed here that the ids are numeric and consist of at least one digit.
Non-regex answer as you asked
\" is an escape sequence in python.
So if {\"Id\":\"135\",\"Type\":0} is a raw string and if you put it into a python variable like
a = '{\"Id\":\"135\",\"Type\":0}'
gives
>>> a
'{"Id":"135","Type":0}'
OR
If the above string is python string which has \" which is already escaped, then do a.replace("\\","") which will give you the string without \.
Now just load this string into a dict and access element Id like below.
import json
d = json.loads(a)
d['Id']
Output :
135

Extra text when using jsondecode

I am trying to come to the point where I create a graph on a given data that I am supposed to read from a text file.
So I use in my code fopen to open the text file, textscan to scan it, than make a string out of it and by using split I want to cut of the first part of every line and use the second part so that I can decode it into json and then use the information.
So my text file consists of two lines of information:
123456.99 :: working completed: result=0 , data ="{"day":"monday", "breakfast":"sandwich"}"
123456.99 :: working completed: result=0 , data ="{"day":"tuesday", "breakfast":"bread"}"
The first part of my code:
fileID = fopen('test1');
text = textscan(fileID, '%s', 'delimiter','\n','whitespace','');
strLog = string(text{1});
res = split(strLog, "data =");
json_str = res(:, 2)
And as a result I get a 2x1 string array. Output:
json_str =
2×1 string array
""{"day":"monday", "breakfast":"sandwich"}""
""{"day":"tuesday", "breakfast":"bread"}""
This is where I got stuck.
My first idea was to call cellfun and apply jsondecode.
But I got
Error using jsondecode JSON syntax error at line 1, column 4
(character 4): extra text.
But it makes no sence to me, since that should be the " from "day" which for json should be okay!?
In json_str you have quote marks " at the start and end. These need to be removed for jsondecode to work. For example J = jsondecode(json_str{1}(2:end-1)).
You can then use cellfun to process all elements. For example,
S = cellfun(#(x)jsondecode(x(2:end-1)),json_str)

How do I find a partial string in a Mongo database using a superset string?

If my database contains entries with the following string values for the "key" field:
"a,b,c"
"a,b,z"
"a,b,c,d,e,f,z"
"d,e,f,g"
"d,e,f,g,z"
"h,i"
And I have a string like this:
"a,b,c,d,e,f,g,h"
How do I find the entries where the value of the key field matches the start of my string? E.g. I want to find the entry where the value of the key field is "a,b,c".
How do I find the entries where the value of the key field matches any part of my string? E.g. I want to find the entries where the value of the key field is "a,b,c" and "d,e,f,g".
To give some context in case anyone thinks this is a pointless task, I want to do stack matching. I will have entries in a database that identify bugs by the first N frames of the stack and then I want to identify bug(s) by the stack obtained from a core dump.
The answer is to use the $where operator. An example in Python, where search_string is the string we want to find matches with, is:
search_string = 'a,b,c,d,e,f,g,h'
js_check = 'function () { var search_string=\'' + search_string + '\'; return search_string.indexOf(this.key) >= 0; }'
matches = my_collection.find({'$where': js_check})

How to generate a Crystal Report from a list of parameters

My requirement is to generate a employee details report of multiple employees.Parameters for query will be employee number and a date range.
This is the record selection formula i'm using
{EMP_LEAVE_REPORT_VIEW.LEAVE_START_DATE} in {?sDate} to {?eDate}
and
(
Stringvar Array strings := Split({?empNoList}, "_");
Numbervar Array numbers;
Redim numbers[Ubound(strings)];
Numbervar i;
for i := 1 to Ubound(strings) do (
numbers[i] := ToNumber(strings[i]);
if {EMP_LEAVE_REPORT_VIEW.EMP_NO} = numbers[i] then
(true;)
else
(false;)
);
)
First i'm checking for the date.
Then i'm taking the employee list as a one string {?empNoList} eg: 5162_5468_5896_5236
and i'm splitting it to separate strings using "_" as the delimiter and assign those values again into a number array and using that value to filter the employee.
But this formula doesn't work.It gives the details of all the employees.
Is this a problem of the way i converted the string array or is there something wrong in the for loop of my code?
I used this code and tried assigning one employee number to the {?empNoList} and it worked.
if (ToNumber({?empNoList}) = {EMP_LEAVE_REPORT_VIEW.EMP_NO}) then true else false
Please help me out with this.Thanks in advance!
I found the solution!
Stringvar Array strings := Split({?empNoList}, "_"); //Spliting and saving the string in a string array
Numbervar Array numbers; //Creating a number array
Redim numbers[Ubound(strings)]; //Declaring number array size
Numbervar i;
//For loop to traverse through string and convert each into numbers and saving them in the numbers array
for i := 1 to Ubound(strings) do (
numbers[i] := ToNumber(strings[i]);
);
if({EMP_LEAVE_REPORT_VIEW.EMP_NO} in numbers) //If condition to check whether Employee number is in the numbers array
then
(true;)
else (false;)
It was a simple out of the box thinking ;)
1) Convert your EMP_LEAVE_REPORT_VIEW.EMP_NO to a string.
2) Then use the Like or In operator with {EMP_LEAVE_REPORT_VIEW.EMP_NO} and {?empNoList}
Simply, search the string version EMP_LEAVE_REPORT_VIEW.EMP_NO inside the bigger string {?empNoList}. You can avoid using the arrays.