I'm building an autofill function that takes a string input and returns a list of string suggestions.
Sequelize's iLike:query returns every string in which the queried string appears. I would like to favour strings for which the query is a prefix. For example when query='sh' then the results should return strings that start with sh instead of having sh anywhere within the string.
This is relatively simple to do after receiving the data from the DB, however I was wondering if there is a way to accomplish this via sequelize while querying the DB? If so how?
The DB size will be between 10,000 and 100,000 strings of no more than a handful of words (company names to be exact).
Optional question: DB's usually have superior performance to generically written code, in this circumstance should there even be a noticeable difference? Or should I just collect all the data from the DB and apply some other filters on it after via vanilla JS.
let suggestions = yield db.Company.findAll({
limit: 7,
where: {
company_name: {
$iLike: '%'+this.data.query
}
}
})
Seems like this is super easy! The '%' acts like a * from regex. So query + '%' returns any results where query is the prefix.
let suggestions = yield db.Company.findAll({
limit: 5,
where: { $or: [
{ stock_ticker: { $ilike: query + '%' } },
{ company_name: { $ilike: query + '%' } }
]},
order: '"volume" DESC'
})
Related
I'm coding a query in my NestTs project, so I would like to retrieve information matched with LIKE clause values.
The problem with my query is the table has three types of records _INFORMED, _UNINFORMED and WITHOUT. If I use the sentence
.where("user.firstName like :name", { name:`%_INFORMED%` })
... It matches with _INFORMED and _UNINFORMED records, then I tried to use the wildcard character as to standard SQL: '%\\_INFORMED%' but it looks wrong.
Do you have any idea? Thanks!
Edit:
Full TYPEORM query:
.createQueryBuilder(Stage, 's')
.innerJoin('s.stageType', 'st')
.leftJoin('s.reasons', 'r')
.select(['s.id', 's.description', 's.name', 'st.id', 'st.name', 'st.displayName', 'r.id', 'r.code', 'r.description'])
.where('st.name like :INFORMED', {
INFORMED: '%\\INFORMED',
})
.orWhere('st.id = :eMeliKeyword', {
eMeliKeyword: StageTypesID.DE_MELI_KEYWORD_ID,
})
.getMany();
Brief history
I have a JavaScript object which stores query templates with $nameParam so that it can be replaced with string.replace(). Issue is that until now I needed $nameParam to be in quotation marks and now I need to get rid of them. Depending on when they are added, the query either works or not. I have observed some interesting behaviour:
Method which replaces string
This method basically calls database and gets records. You can see the longest line - it's responsible for replacing $nameParam with the provided parameter.
function setupEndpoint(app) {
app.get('/neo4jdb/:queryType',
async (req, res) => {
const session = driver.session();
res.on('finish', () => session.close());
try {
const response = await session.run(queryTemplates[req.params.queryType],
{ nameParam: req.query.name });
let statement = response.summary.query.text.replace('$nameParam', `"${response.summary.query.parameters.nameParam}"`);
statement = statement.replace('RETURN', '\nRETURN');
console.info(`Neo4j statement: ${statement}`);
res.send({ rawItems: response.records, statement });
} catch (err) {
console.error('Error connecting Neo4j', configs);
console.error(err);
res.send({ error: 'Error connecting Neo4j' });
}
});
}
Working example
Query template
const queryTemplates = {
getShipsForCompany: `MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-()
WHERE A.name=$nameParam RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50`
};
Replacement
response.summary.query.text.replace('$nameParam', `"${response.summary.query.parameters.nameParam}"`);
Produced output
Neo4j statement: MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-() WHERE A.name="TRINITY HOUSE"
RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50
Not-working example
Query template
const queryTemplates = {
getShipsForCompany: `MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-()
WHERE A.name="$nameParam" RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50`
};
Replacement
response.summary.query.text.replace('$nameParam', `${response.summary.query.parameters.nameParam}`);
Produced output
Neo4j statement: MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-() WHERE A.name="TRINITY HOUSE"
RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50
Summary
Both produced output queries are the same. Why first one returns results and second one is empty? (2nd one copied to DB engine works fine)
Neo4j cypher syntax is below.
WHERE A.name=$nameParam
It should NOT have double quotes on the parameter name. Thus, the 2nd example is syntax error during runtime.
I have a query thats being fed into MySQL. I added a new component.. a LIKE.
It works fine for a singular item, but when I pass in multiples... it does some weird escape of the single quotes.
Here is what the sql passed in looks like (from the console.log below):
sql: 'select name, street, numbers from' +
"`HOMES` where " +
"year='2020' and vals in ('2.2.3\\',\\'2.4.5')",
values: [ '2020', "2.2.3','2.4.5"]
Here is how I build the vals:
sql += " and vals in (?)";
var newStr = filterText.myItems.split(",".join("','");
sqlParams.push(newStr);
filterText.myItems is entered by the user as a comma separated value. For example: "2.2.3,2.4.5"
The query going into MySQL is built like this:
exports.query = function(sql, params, resultHandler, errorHandler) {
function _handleError(err) {
errorHandler(config.mysql.errorMessage || err);
}
pool.getConnection(function(err, conn) {
if(err) {
_handleError(err);
return;
}
var query22 = conn.query(sql, params, function(err,results) {
if(err) {
_handleError(err);
} else {
resultHandler(results);
}
conn.release();
});
//this prints out the sql and values displayed above.
console.log("FINAL QUERY:"+util.inspect(query22));
}
}
Needless to say... this fails to execute as I guess MySQL has no idea what the \\' actually is.
For whatever reason the query adds the leading and trailing single quotes. This is why I add the ',' in between the numbers.
Anyone know what might be causing this or how I can remove it before it executes?
thanks!
After messing around some more I finally got it to work. Here is how.
The sql was built and params passed in like this:
sql = "select name, street, numbers from ?? where year=?",
sqlParams = [this.tableName, this.year]
I was dynamically adding to my sql with the in clause. However, when I made it part of the main sql and passed in the vals there it worked!
sql = "select name, street, numbers from ?? where year=? and vals in (?)",
sqlParams = [this.tableName, this.year, filterText.myItems.split(',')]
The sql going in now looks like this and works great:
sql: 'select name, street, numbers from' +
"`HOMES` where " +
"year='2020' and vals in ('2.2.3','2.4.5')",
values: [ '2020', ['2.2.3','2.4.5'] ]
I have extracted a string from stored procedure in Microsoft SQL Server 2008 R2,
using this query:
EXEC sp_helptext 'MyStoredProcedureName'; I need to split this string into arrays or sub strings starting from the ending parenthesize " ] " and ending with the word "As".
I have to save ALL fields starting with "#" in (fieldsArray) and the types of these fields -After the space- in (typeArray) and then output them to a file in node.js with this format:
InvoiceNo: {
type: DataType.String(255),
},
Here is the extracted string:
CREATE PROCEDURE [dbo].[MyStoredProcedureName]
#InvoiceNo int
,#TransDate datetime
,#CustomerID bigint
,#CurrencyID bigint
,#SalesInvoiceTypeID bigint
,#DiscountAmount nvarchar(50)
,#DetailXml ntext
,#TotalAll float
,#TotalBefore float
,#TaxAmount float
,#OtherExpenses float
,#OutVouchersNo nvarchar(1000)
,#Notes nvarchar(1000)
,#TotalWiegts float
,#VoucherDefID bigint
,#SalesmanID bigint
,#IsSale bit
AS
BEGIN TRANSACTION
Edit: I used another query instead of the mentioned above. Now I have an object containing the result of the query which is the Names of the fields each in separate line. What I need to do now is to separate this object to a string array so that I can deal with each name separately.
the object "Names" contain the result of the query that I used:
Names = await sequelize.query(namesQuery);
And this is the output of console.log(Names);
[ [ { '': 'InvoiceNo' },
{ '': 'TransDate' },
{ '': 'CustomerID' },
{ '': 'CurrencyID' },
{ '': 'SalesInvoiceTypeID' },
{ '': 'DiscountAmount' },
I tried Names.split but I got the error "Names.split is not a function"
You could query the Sys.Parameters table instead:
SELECT Substring(Parameters.Name,2,255) + ': { type: DataType.' +
CASE types.Name
WHEN 'varchar' THEN 'String(' + CAST(Parameters.Max_Length As Varchar)
WHEN 'int' THEN 'Int'
ELSE 'COMPLETE THE REST OF THIS yourself.....'
END + '),},'
FROM Sys.Parameters
INNER JOIN sys.procedures on parameters.object_id = procedures.object_id
INNER JOIN sys.types on parameters.system_type_id = types.system_type_id AND parameters.user_type_id = types.user_type_id
Where procedures.name = 'MyStoredProcedureName'
If you consider that the symbol # is only used to identify the beginning of a field name, you can use regular expressions as follows:
let result = {}
str.match(/#\w+ [a-z]+/g)
.map(s => s.match(/#(\w+) ([a-z]+)/))
.forEach(r => {
let fieldName = r[1]
let type = r[2]
result[fieldName] = { type }
})
console.log(JSON.stringify(result, undefined, 2))
This will output
{
"InvoiceNo": {
"type": "int"
},
"TransDate": {
"type": "datetime"
},
...
}
I guess the same could be achieved with only regex, but the code is easier to understand this way:
the first match captures all the #FieldName type strings
the second match captures for each of these FieldName and type
the last one fills the object result with members of name FieldName and content { type: "type" }
the last command formats everything and outputs to the console
Is it possible to convert mongo objectId into string.
The above pictures shows data i received and shown in console.I need id value in string form .but ObjectId is returning as object
In Database id is look like this- 565d3bf4cefddf1748d1fc5e -objectId and i need id exactly like this –
According to the Mongo documentation:
a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.
You can check it out here: https://docs.mongodb.org/manual/reference/object-id/
So in javascript you could do something like this.
var mId = {
Timestamp:1448950573,
Machine:13565407,
Pid:1756,
Increment:8888962
};
function getId(mongoId) {
var result =
pad0(mongoId.Timestamp.toString(16), 8) +
pad0(mongoId.Machine.toString(16), 6) +
pad0(mongoId.Pid.toString(16), 4) +
pad0(mongoId.Increment.toString(16), 6);
return result;
}
function pad0(str, len) {
var zeros = "00000000000000000000000000";
if (str.length < len) {
return zeros.substr(0, len-str.length) + str;
}
return str;
}
console.log(getId(mId))
It produces "565d3b2dcefddf06dc87a282" which was not exactly the id you had, but that might just be a tweak or i was working with different data :D.
EDIT
Added a padding function so that zeros are not truncated.
Hope that helps
EDIT:
I assume you are using c# to connect to and serve documents from the mongo DB. In that case, there is a driver that also supports toString().
Here is an example using the mongo csharp driver:
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
// ...
string outputFileName; // initialize to the output file
IMongoCollection<BsonDocument> collection; // initialize to the collection to read from
using (var streamWriter = new StreamWriter(outputFileName))
{
await collection.Find(new BsonDocument())
.ForEachAsync(async (document) =>
{
using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonWriter(stringWriter))
{
var context = BsonSerializationContext.CreateRoot(jsonWriter);
collection.DocumentSerializer.Serialize(context, document);
var line = stringWriter.ToString();
await streamWriter.WriteLineAsync(line);
}
});
}
ORIGINAL:
These are Mongo ObjectId's and if you haven't already deserialised the document they should support a toString method that will return a hexadecimal string.
but if you want this applied to the whole document, using JSON.stringify(MogoDocument) should deserialize this for you into a plain object.