MongoDB C driver: how to use regex query collection? - c++

for example, In MySQL the query like this:
select name from test_tab where id = 1 and name like 'test%';
I want to translate this query in mongodb by mongodb C driver, so I write the code like this, but all don't work(the searchDoc() function is okay.
string strName = "";
bson_t *cond = bson_new();
BSON_APPEND_INT32(cond, "id", 1);
if (strlen(name.c_str()) > 0)
{
strName = "/^" + name + "/";
bson_t *child;
child = bson_new();
bson_append_document_begin(cond, "name", -1, child);
BSON_APPEND_UTF8(child, "$regex", strName.c_str());
bson_append_document_end(cond, child);
}
mongoc_cursor_t *cursor(NULL);
int iRet = searchDoc("db", "test_tab", cond, cursor);
if (iRet < 0)
{
bson_destroy(cond);
mongoc_cursor_destroy(cursor);
return -1;
}
and
string strName = "";
bson_t *cond = bson_new();
BSON_APPEND_INT32(cond, "id", 1);
if (strlen(name.c_str()) > 0)
{
strName = "/^" + name + ".*/";
BSON_APPEND_REGEX(cond, "name", strName.c_str(), "i");
}
mongoc_cursor_t *cursor(NULL);
int iRet = searchDoc("db", "test_tab", cond, cursor);
if (iRet < 0)
{
bson_destroy(cond);
mongoc_cursor_destroy(cursor);
return -1;
}
How can I build the regex pattern to query record work okay?
Thank you

I seach this page: https://jira.mongodb.org/browse/CDRIVER-206,
there is a important tips: "You do not need to include the forward-slash when building a regex."
so I delete the forward-slash, my code
strName = "/^" + name + ".*/";
BSON_APPEND_REGEX(cond, "name", strName.c_str(), "i");
change to
strName = "/^" + name + ".*/";
BSON_APPEND_REGEX(cond, "name", strName.c_str(), "i");
It can work. My problem has been solved.

Related

Parameterized Query Returns no Results using C++ .Net MySQL Connector

I cannot seem to find any resolution to this issue on my own. I use this generic function to retrieve data from a database like so:
int id = 29
ArrayList^ classes = getClassesGeneric("dep_id", "=", id.ToString());
However, this returns no results. If I query the database through MySQL Workbench or without parameters it works fine. What am I missing?
ArrayList^ Accessor::getClassesGeneric(String^ col, String^ op, String^ value)
{
ArrayList^ result = gcnew ArrayList();
this->cmd = gcnew MySqlCommand("SELECT * FROM rpos_db.classes WHERE #col #op #value;", this->con);
try
{
this->cmd->Parameters->AddWithValue("#col", col);
this->cmd->Parameters->AddWithValue("#op", op);
this->cmd->Parameters->AddWithValue("#value", value);
this->cmd->Prepare();
MySqlDataReader^ r = this->cmd->ExecuteReader();
while (r->Read())
{
Class^ c = gcnew Class();
c->id = r->GetInt32(0);
c->dep_id = r->GetInt32(1);
c->name = r->GetString(2);
c->code = r->GetString(3);
result->Add(c);
}
r->Close();
}
catch (Exception^ ex)
{
MessageBox::Show(ex->StackTrace, ex->Message);
}
return result;
}
Using the function like this produces the indented result:
classes = getClassesGeneric("1", "=", "1");
Parameters can only be used to replace literals, not object names or syntactic elements, such as the = operator. You'd either have to hardcode it. If you want to pass them dynamically, you'd have to use string manipulation:
ArrayList^ Accessor::getClassesGeneric(String^ col, String^ op, String^ value)
{
ArrayList^ result = gcnew ArrayList();
this->cmd = gcnew MySqlCommand
("SELECT * FROM rpos_db.classes WHERE " +
col + " " + op + " #value;", this->con);
try
{
this->cmd->Parameters->AddWithValue("#value", value);
this->cmd->Prepare();
MySqlDataReader^ r = this->cmd->ExecuteReader();

QString parse system variables

How I should parse QString, which contains system variables ?What I want:
QString path = "%WINDIR%\\System32\\";
QString output = parse(path);
QDebug()<<output; \\ output is "C:\\Windows\\System32\\"
I think you want something like this:
// Untested
QString parse(QString str)
{
int pos = 0;
QRegExp rx("%([^%]+)%"); // Match env var between two '%'
rx.setMinimal(true);
while((pos = rx.indexIn(str, pos)) != -1)
{
// Replace env var
QString capture = rx.cap(1);
QString replacement = getenv(capture.toAscii());
str.replace("%" + capture + "%", replacement);
// Skip env var + two '%'
pos += rx.matchedLength() + 2;
}
return str;
}
QString path = parse("%WINDIR%\\System32");
I think, this is what you looking for. Please try this
QString windir = getenv ("WINDIR"); // Expanded
if (windir.isEmpty()) {
fprintf(stderr, "Generator requires WINDIRto be set\n");
}
windir += "\\System32";
qDebug()<<windir;

webcrawler link extraction problem

im writing a simple webcrawler. the problem is, with the link extraction.
i uses the cpp-netlib with boost. here a few lines of my CLink Class.
CLink::CLink(const CLink& father, const std::string& relUrl )
{
uri = relUrl;
boost::network::uri::uri instance(relUrl);
boost::network::uri::uri instanceFather(father.uri);
if ( (valid = boost::network::uri::is_valid(instance)) == 1)
{
scheme = boost::network::uri::scheme(instance);
user_info = boost::network::uri::user_info(instance);
host = boost::network::uri::host(instance);
port = boost::network::uri::port(instance);
path = boost::network::uri::path(instance);
query = boost::network::uri::query(instance);
fragment = boost::network::uri::fragment(instance);
uri = scheme;
uri += "://";
uri += host;
uri += path;
}
else
{
if ( (valid = boost::network::uri::is_valid(instanceFather)) == 1)
{
scheme = boost::network::uri::scheme(instanceFather);
user_info = boost::network::uri::user_info(instanceFather);
host = boost::network::uri::host(instanceFather);
port = boost::network::uri::port(instanceFather);
path = boost::network::uri::path(instance);
query = boost::network::uri::query(instance);
fragment = boost::network::uri::fragment(instance);
uri = scheme;
uri += "://";
uri += host;
uri += path;
}
}
};
CLink::CLink( const std::string& _url )
{
uri = _url;
boost::network::uri::uri instance(_url);
if ( (valid = boost::network::uri::is_valid(instance) ) == 1)
{
scheme = boost::network::uri::scheme(instance);
user_info = boost::network::uri::user_info(instance);
host = boost::network::uri::host(instance);
port = boost::network::uri::port(instance);
path = boost::network::uri::path(instance);
query = boost::network::uri::query(instance);
fragment = boost::network::uri::fragment(instance);
uri = scheme;
uri += "://";
uri += host;
uri += path;
}
else
std::cout << "err " << std::endl;
};
the links from the webpage i took with the htmlcxx lib. i took the HTML::Node and normalize them wih the boost filesystem.
if ( url.find("http://") == std::string::npos)
{
std::string path = link.get_path() + url;
url = link.get_host() + path;
boost::filesystem::path result;
boost::filesystem::path p(url);
for(boost::filesystem::path::iterator it=p.begin(); it!=p.end(); ++it)
{
if(*it == "..")
{
if(boost::filesystem::is_symlink(result) )
result /= *it;
else if(result.filename() == "..")
result /= *it;
else
result = result.parent_path();
}
else if(*it == ".")
{
// Ignore
}
else
{
// Just cat other path entries
result /= *it;
}
}
url = "http://" + result.string();
}
return ret;
Now the problem is.
i try to fetch http://www.wikipedia.de/ and i get the urls like
properties
http://wikimedia.de/wiki/Vereinszeitung
... ...
and on the site http://wikimedia.de/wiki/Vereinszeitung there is a link like /wiki/vereinsatzung
so often i get links like
http://wikimedia.de/wiki/Vereinszeitung/wiki/Freies_Wissen
does someone have a idee?
You need to have a special case for absolute links (those that start with /).
If the href starts with /, then the resulting link should be (using the terms from The URI template which come from the RFC):
[scheme]://[authority][what you got in href]
What you are currently constructing is:
[scheme]://[authority][path][what you got in href]
So you're duplicating the path information.
So if link.get_path() starts with /, you should simply change:
std::string path = link.get_path() + url;
url = link.get_host() + path; // this is incorrect btw, missing the [port]
to
url = link.get_host() + ":" + link.get_port() + url;
It would probably be cleaner to do the path normalization on the path only, not on the URL (i.e. add host:port after normalizing the path).
[And I think your code will fail if it encounters an https link.]

open desktop using QText Browser

Right now I am displaying something like /home/binary/ in QText browser. Now I want the open the folder by clicking on this text. How to do that ? Thanks in advance
Here is my sample code. I am display the result
s
bool MainWindow::displayResult(multimap<string,
string> &resultMap, string &filePath)
{
multimap::iterator iter;
bool fileStatus = false;
int noOfLocFound = 0, forAppending = 0;
QString no;
noOfLocFound = resultMap.size();
if ( noOfLocFound != 0 )
ui->textBrowser->append( "<i>File found at <b>" + no.setNum (
noOfLocFound ) + " locations");
for ( forAppending = 0,iter = resultMap.begin(); iter !=
resultMap.end(); iter++,
forAppending++ )
{
string file = iter->first;
string dir = iter->second;
if ( forAppending == 0)
filePath.append(dir);
else
filePath.append(","+dir);
QString qdir = QString::fromStdString(dir);
cout << "Display";
ui->textBrowser->append( qdir );
fileStatus = true;
}
if ( fileStatus == false )
{
ui->textBrowser->append("File not
found");
return false;
}
return true;
}
By "open the folder", do you mean, open a file dialog for the user to select something inside of the given directory?
If so, you would probably want to connect your QTextBrowser's clicked signal to a slot that looked something like:
// connect events, in MyWindow constructor, or whereever...
connect(textbrowser, SIGNAL(mousePressEvent(QMouseEvent*)), this, SLOT(openFileDialog(QMouseEvent*)));
void MyWindow::openFileDialog(QMouseEvent* event) {
Q_UNUSED(event);
QStringList files = QFileDialog::getOpenFileNames(this, "Select a file...",
textbrowser.plainText());
// do something with the files here...
}

List of windows users remotely

I would like to know how to retrieve the list of users that are logged onto a Remote machine. I can do it with qwinsta /server:xxxx, but would like to do it in C#.
check out wmi in .net under system.management.
something like:
ConnectionOptions conn = new ConnectionOptions();
conn.Authority = "ntdlmdomain:NAMEOFDOMAIN";
conn.Username = "";
conn.Password = "";
ManagementScope ms = new ManagementScope(#"\\remotecomputer\root\cimv2", conn);
ms.Connect();
ObjectQuery qry = new ObjectQuery("select * from Win32_ComputerSystem");
ManagementObjectSearcher search = new ManagementObjectSearcher(ms, qry);
ManagementObjectCollection return = search.Get();
foreach (ManagementObject rec in return)
{
Console.WriteLine("Logged in user: " + rec["UserName"].ToString());
}
You may not need the ConnectionOptions...
I ended up using the qwinsta /server:server1 command from C# -- it was much easier
thanks Ken
All this checks all 8 servers at the same time -- I put the result in sql server
but you can do what ever you want
query_citrix.bat script
cd C:.......\bin\citrix_boxes
qwinsta -server:servername or ip > servername.txt
string sAppCitrixPath = Application.StartupPath.ToString() + "\\citrix_boxes\\";
//Run Script for current citrix boxes
Process proc = new Process();
ProcessStartInfo si = new ProcessStartInfo();
si.FileName = sAppCitrixPath + "query_citrix.bat";
proc.StartInfo = si;
proc.Start();
proc.WaitForExit();
int exitCode = proc.ExitCode;
proc.Close();
if (exitCode == 0)
{
//Execute update who is on the Citrix_Boxes Currently
DirectoryInfo dic = new DirectoryInfo(sAppCitrixPath);
FileInfo[] fic = dic.GetFiles("*.txt");
for (int i = 0; i < fic.Length; i++)
{
ParseQWinStaServerFile(fic[i].FullName.ToString(), fic[i].Name.ToString().ToUpper().Replace(".TXT",""));
File.Delete(fic[i].FullName.ToString());
}
}
private void ParseQWinStaServerFile(string sLocation,string sServer)
{
using (StreamReader sr = File.OpenText(sLocation))
{
string sRecord = String.Empty;
char[] cSep = new char[] {' '};
bool bFirst = true;
while ((sRecord = sr.ReadLine()) != null)
{
if (bFirst == false)
{
string[] items = sRecord.Split(cSep, StringSplitOptions.RemoveEmptyEntries);
//Make sure all columns are present on the split for valid records
if (sRecord.Substring(19, 1) != " ") // check position of user id to see if it's their
{
//Send the user id and server name where you want to.
//here is your user
id = items[1].ToString().ToLower().Trim()
//here is your server
};
}
else
{
bFirst = false;
}
}
}
}