how to use .populate() in javascript - javascript

I have a collection called
CR
what I want to do is query CR like so:
let cre = await CR.find({myid: "xxxxxx"})
and i also have a collection called cla, but that one i need to query based off of the results of cre. The results of cre will return a class_id, in which I need to use to query the cla collection to find the _id. At the end of all of this, I want to ideally merge the two, which I believe you can do through .populate(), and then send it to teh front-end as one.;
I have tried this:
let cre = await cr.find({myid: "xxx"}).populate('loc').populate('desc').populate('dt');
but this isn't working. how can I fix this?

It may be due to schemas, but this is how it's clean and simple to use;
let cre = await cr.find({myid: "xxx"}).populate(['loc','desc','dt']);

Firstly, you can take cla collection "_id" in CR collection schema. In schema of CR collection refer to cla model id like this,
const creSchema = mongoose.Schema({
name: String,
classnId: { type: mongoose.Types.ObjectId, ref: "Cla" }
});
Then you can populate like,
const cres = await CR.find({}).populate({path:'classnId', select:'columnName'});
Hopefully, this will solve your issue.
Note: There in populating you can give multiple column names by space and if you give a minus before a column name like this (-columnName) then that column will not show when you will call the API.

Related

Sequelize how to return result as a 2D array instead of array of objects?

I am using Sequelize query() method as follows:
const sequelize = new Sequelize(...);
...
// IMPORTANT: No changed allowed on this query
const queryFromUser = "SELECT table1.colname, table2.colname FROM table1 JOIN table2 ON/*...*/";
const result = await sequelize.query(queryFromUser);
Because I am selecting two columns with identical names (colname), in the result, I am getting something like:
[{ "colname": "val1" }, { "colname": "val2" }...], and this array contains values only from the column table2.colname, as it is overwriting the table1.colname values.
I know that there is an option to use aliases in the SQL query with AS, but I don't have control over this query.
I think it would solve the issue, if there was a way to return the result as a 2D array, instead of the array of objects? Are there any ways to configure the Sequelize query that way?
Im afraid this will not be possible without changes in the library directly connecting to the database and parsing its response.
The reason is:
database returns BOTH values
then in javascript, there is mapping of received rows values to objects
This mapping would looks something like that
// RETURNED VALUE FROM DB: row1 -> fieldName:value&fieldName:value2
// and then javascript code for parsing values from database would look similar to that:
const row = {};
row.fieldName = value;
row.fieldName = value2;
return row;
As you see - unless you change the inner mechanism in the libraries, its impossible to change this (javascript object) behaviour.
UNLESS You are using mysql... If you are using mysql, you might use this https://github.com/mysqljs/mysql#joins-with-overlapping-column-names but there is one catch... Sequelize is not supporting this option, and because of that, you would be forced to maintain usage of both libraries at ones (and both connected)
Behind this line, is older answer (before ,,no change in query'' was added)
Because you use direct sql query (not build by sequelize, but written by hand) you need to alias the columns properly.
So as you saw, one the the colname would be overwritten by the other.
SELECT table1.colname, table2.colname FROM table1 JOIN table2 ON/*...*/
But if you alias then, then that collision will not occur
SELECT table1.colname as colName1, table2.colname as colName2 FROM table1 JOIN table2 ON/*...*/
and you will end up with rows like: {colName1: ..., colName2: ...}
If you use sequelize build in query builder with models - sequelize would alias everything and then return everything with names you wanted.
PS: Here is a link for some basics about aliasing in sql, as you may aliast more than just a column names https://www.w3schools.com/sql/sql_alias.asp
In my case I was using:
const newVal = await sequelize.query(query, {
replacements: [null],
type: QueryTypes.SELECT,
})
I removed type: QueryTypes.SELECT, and it worked fine for me.

Similar string matching in Sequelize MYSQL

I'm new to Sequelize and JS and might not know all operators so I want to ask if there's any way to retrieve an entry from a database which is similar to but not an exact match. So for example the string I'm searching for is +921234567890 but in the database its stored as +92-1234567890, separated with a hyphen for country dialing codes.
The db I'm using is MySQL.
I tried this which I know is incorrect but I'm not sure how to move ahead:
where: {
cell: {
[Op.or]: {
[Op.like]: "%-%",
[Op.eq]: cellNumber,
},
},
You can use the REGEX_REPLACE() sql function to replace any non-numeric characters in the cell column before comparing to your input. Use the sequelize.where(), sequelize.fn(), and sequelize.col() functions to generate the query. Assuming your table is model and Model is Model.
const cellNumber = 1234567890;
const results = await Model.findAll({
where: sequelize.where(
sequelize.fn('REGEXP_REPLACE', sequelize.col('model.cell'), '[a-zA-Z]+', ''),
'=',
cellNumber
),
});
This should generate SQL similar to:
SELECT * FROM `model`
WHERE REGEXP_REPLACE(`model`.`cell`, '[a-zA-Z]+', '') = 1234567890;
The solution to this issue was solved using raw sql query but for anyone looking for an answer when using REGEXP_REPLACE, you should use REPLACE with sequelize.literal:
cell: { [Op.eq]: this.sequelize.literal("REPLACE('cell','-','')") }

How to create a copy of mongoose's Aggregate object?

I need a way to duplicate and dynamically modify my requests to the database. With regular mongoose Query objects I can create a copy of the query with x = query.toConstructor() and later fire multiple requests with additional parameters, e.g.:
var sample = x().limit(5);
var totalCount = x().count();
However mongoose's Aggregate objects lack the toConstructor function. Is there any way to achieve same results with an Aggregate object?
The following solution worked for me well, though not so nice.
const withoutId = Model.aggregate().project({ _id: false });
const totalCount = Model.aggregate(withoutId.pipeline()).count('count');
Hope this will help at least others.

Parse - Create an AND query of two OR queries

I need to do the following query in Parse.com (pseudo language):
select all posts where
(expired < today OR expired not exists)
AND
(owner is {user} OR commenter contains {user})
I know in Javascript I can create the two OR queries using Parse.Query.or, but since there doesn't seems to be a Parse.Query.and variant, I don't know how I can combine these two OR queries into a single query.
Other people have suggested to simply use equalTo multiple times to create AND statements, but this doesn't work for a composed OR query.
I'm not familiar with Parse and this is too long for a comment, but see below from the documentation; the last sentence in particular seems to be what you're after.
Compound Queries
If you want to find objects that match one of several queries, you can use Parse.Query.or method to construct a query that is an OR of the queries passed in. For instance if you want to find players who either have a lot of wins or a few wins, you can do:
var lotsOfWins = new Parse.Query("Player");
lotsOfWins.greaterThan("wins", 150);
var fewWins = new Parse.Query("Player");
fewWins.lessThan("wins", 5);
var mainQuery = Parse.Query.or(lotsOfWins, fewWins);
mainQuery.find({
success: function(results) {
// results contains a list of players that either have won a lot of games or won only a few games.
},
error: function(error) {
// There was an error.
}
});
You can add additional constraints to the newly created Parse.Query that act as an 'and' operator.
You can use both AND with OR like this. Attributes in the AND being the equalTo valuables.
const mainQuery = Parse.Query.or(
Parse.Query.and(lotsOfWins, fewWins2),
Parse.Query.and(lotsOfWins2, fewWins)
);
You can add as many as you like..
const lotsOfWins = new Parse.Query("CLASS");
lotsOfWins.equalTo('user', CurrentUser);
const fewWins = new Parse.Query("CLASS");
fewWins.equalTo('recipient', CurrentUser);

mongodb/meteor collection check if subdocument field exists when field is a variable

I'm trying to use something as follows
collection.find({"myField."+variable : {$exists: true})
But obviously that doesn't work because the collections doesn't take strings. Instead, I tried building a a fully query string in JSON but that won't parse correctly because I'm just searching for a field name and not an entire object
var qry = '{"myField.'+variable+'"}'; //no go
I've also tried the meteor collection fields logic
var qry = 'myField.'+variable;
collection.find({}, {fields: {qry: 1}})
to no avail. I know that a query can take a JSON object but I'm not sure how to write this up.
Give this a try:
var selector = {};
selector["myField." + variable] = {$exists: true};
Collection.find(selector);
This can be accomplished using bracket notation
var fieldQuery = {};
fieldQuery["myField"+variable] = {$exists: true};
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation

Categories

Resources