cube.js - mongodb DBref field inside schema dimension section - mongodb

I am trying to create a filter on DBref id field (mongodb). The SQL query generated is given below
SELECT
`part_r_f_q_dpa`.`partRFQId` `part_r_f_q_dpa__partrfqid`,
`part_r_f_q_dpa`.`noOfApproval` `part_r_f_q_dpa__noofapproval`,
`part_r_f_q_dpa`.`CurrentApproved` `part_r_f_q_dpa__currentapprove`
FROM
makethepart.`directPartApproval` AS `part_r_f_q_dpa`
LEFT JOIN makethepart.`partRFQ` AS `part_r_f_q` ON `part_r_f_q_dpa`.partRFQId = `part_r_f_q`._id
WHERE
(`part_r_f_q`.`creatorBuyer.$id` = ?)
GROUP BY
1,
2,
3
ORDER BY
1 ASC
LIMIT
10000
I am getting an error "Error: Unknown column 'part_r_f_q.creatorBuyer.$id' in 'where clause'".
The code excerpt under dimensions in the schema is as below
creatorbuyer: {
sql: `${CUBE}.\`creatorBuyer.$id\``,
type: string
can someone please let me know how should we handle the dbrefs ids as shown above

$id in Mongo BI is referenced as _id. You should use _id instead of $id.

Related

How to sort a collection by row in MongoDB?

I am using MongoDB with hapi.JS. I have a collection which contains few rows in the schema. I want to sort the rows in either asc order or desc order but want to mention it in the URI. for example the URI should look something like this
/api/v1/customers?sort=name&direction=asc&limit=30
How can I sort this collection by asc or desc order and limit can be fixed or flexible as well.
I have defined like this as of now but even if I mention the sort in URI it gives the output only in asc order.
Models.Account.find(criteria,projection,{skip:5,limit:5},function(err,resp){
if(err)
callbackRoute(err);
else
callbackRoute(err,resp);
}).sort({[_id]:"asc"});
db.yourcollection.find(...).sort({ name:1 }).limit(30)
or with dynamic values:
// following is ECMA 6 only
// get params and make sure values are what you expect (check for injection) + direction must be = "asc" || "desc"
db.yourcollection.find(...).sort({ [sort]: direction }).limit(30)

MongoDB php subquery

i'm new to nosql and currently trying to work with mongodb.
From sql statement:
select id from table1 where id in (select related_id from table2 where column_name='somevalue')
what would be the equivalent mongodb/php syntax of this query ?
I have populated the 2 collections with sample data, trying to figure out with aggregate but no results so far. There are plenty of samples around but couldn't find something of this type of sub-query.
Any help is appreciated.
get the ids from table2
ids = db.table2.find({ "columnname": "somevalue"},{ id: 1, _id: 0 })
query the table1 collection with the ids from previous query
db.table1.find({ "_id": { "$in": ids } },{id:1,_id:0})

Mongodb find query using $or

Please Help.
I am trying to create the query in mongodb like (in MySql):
SELECT * FROM user WHERE user_id = '1' AND (type = 'admin' OR type = 'requester') ORDER BY user_id DESC
How do I convert this query into mongodb find({})?
I'd use $in instead of $or since only a single field is involved:
db.user.find({
user_id:"1",
type: {$in:["admin","requester"]}
}).sort({"user_id":-1});
Check this,
db.user.find({user_id:"1",$or:[{"type":"admin"},{"type":"manager"}]})

Getting a MongoDB document's field value into a variable

I am using mongo's shell and want to do what is basically equivalent to "SQL's select col INTO var" and then use the value of var to look up other rows in the same table or others (Joins). For example, in PL/SQL I will declare a variable called V_Dno. I also have a table called Emp(EID, Name, Sal, Dno). I can access the value of Dno for employee 100 as, "Select Dno into V_Dno from Emp where EID = 100). In MongoDB, when I find the needed employee (using its _id), I end up with a document and not a value (a field). In a sense, I get equivalent to the entire row in SQL and not just a column. I am doing the following to find the given emp:
VAR V_Dno = db.emp.find ({Eid : 100}, {Dno : 1});
The reason I want to do this to traverse from one document into the other using the value of a field. I know I can do it using the DBRef, but I wanted to see if I could tie documents together using this method.
Can someone please shed some light on this?
Thanks.
find returns a cursor that lets you iterate over the matching documents. In this case you'd want to use findOne instead as it directly returns the first matching doc, and then use dot notation to access the single field.
var V_Dno = db.emp.findOne({Eid : 100}, {Dno : 1}).Dno;
Using your query as a starting point:
var vdno = db.emp.findOne({Eid: 100, Dno :1})
This returns a document from the emp collection where the Eid = 100 and the Dno = 1. Now that I have this document in the vdno variable I can "join" it to another collection. Lets say you have a Department collection, a document in the department collection has a manual reference to the _id field in the emp collection. You can use the following to filter results from the department collection based on the value in your variable.
db.department.find({"employee._id":vdno._id})

Select most reviewed courses starting from courses having at least 2 reviews

I'm using Flask-SQLAlchemy with PostgreSQL. I have the following two models:
class Course(db.Model):
id = db.Column(db.Integer, primary_key = True )
course_name =db.Column(db.String(120))
course_description = db.Column(db.Text)
course_reviews = db.relationship('Review', backref ='course', lazy ='dynamic')
class Review(db.Model):
__table_args__ = ( db.UniqueConstraint('course_id', 'user_id'), { } )
id = db.Column(db.Integer, primary_key = True )
review_date = db.Column(db.DateTime)#default=db.func.now()
review_comment = db.Column(db.Text)
rating = db.Column(db.SmallInteger)
course_id = db.Column(db.Integer, db.ForeignKey('course.id') )
user_id = db.Column(db.Integer, db.ForeignKey('user.id') )
I want to select the courses that are most reviewed starting with at least two reviews. The following SQLAlchemy query worked fine with SQlite:
most_rated_courses = db.session.query(models.Review, func.count(models.Review.course_id)).group_by(models.Review.course_id).\
having(func.count(models.Review.course_id) >1) \ .order_by(func.count(models.Review.course_id).desc()).all()
But when I switched to PostgreSQL in production it gives me the following error:
ProgrammingError: (ProgrammingError) column "review.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT review.id AS review_id, review.review_date AS review_...
^
'SELECT review.id AS review_id, review.review_date AS review_review_date, review.review_comment AS review_review_comment, review.rating AS review_rating, review.course_id AS review_course_id, review.user_id AS review_user_id, count(review.course_id) AS count_1 \nFROM review GROUP BY review.course_id \nHAVING count(review.course_id) > %(count_2)s ORDER BY count(review.course_id) DESC' {'count_2': 1}
I tried to fix the query by adding models.Review in the GROUP BY clause but it did not work:
most_rated_courses = db.session.query(models.Review, func.count(models.Review.course_id)).group_by(models.Review.course_id).\
having(func.count(models.Review.course_id) >1) \.order_by(func.count(models.Review.course_id).desc()).all()
Can anyone please help me with this issue. Thanks a lot
SQLite and MySQL both have the behavior that they allow a query that has aggregates (like count()) without applying GROUP BY to all other columns - which in terms of standard SQL is invalid, because if more than one row is present in that aggregated group, it has to pick the first one it sees for return, which is essentially random.
So your query for Review basically returns to you the first "Review" row for each distinct course id - like for course id 3, if you had seven "Review" rows, it's just choosing an essentially random "Review" row within the group of "course_id=3". I gather the answer you really want, "Course", is available here because you can take that semi-randomly selected Review object and just call ".course" on it, giving you the correct Course, but this is a backwards way to go.
But once you get on a proper database like Postgresql you need to use correct SQL. The data you need from the "review" table is just the course_id and the count, nothing else, so query just for that (first assume we don't actually need to display the counts, that's in a minute):
most_rated_course_ids = session.query(
Review.course_id,
).\
group_by(Review.course_id).\
having(func.count(Review.course_id) > 1).\
order_by(func.count(Review.course_id).desc()).\
all()
but that's not your Course object - you want to take that list of ids and apply it to the course table. We first need to keep our list of course ids as a SQL construct, instead of loading the data - that is, turn it into a derived table by converting the query into a subquery (change the word .all() to .subquery()):
most_rated_course_id_subquery = session.query(
Review.course_id,
).\
group_by(Review.course_id).\
having(func.count(Review.course_id) > 1).\
order_by(func.count(Review.course_id).desc()).\
subquery()
one simple way to link that to Course is to use an IN:
courses = session.query(Course).filter(
Course.id.in_(most_rated_course_id_subquery)).all()
but that's essentially going to throw away the "ORDER BY" you're looking for and also doesn't give us any nice way of actually reporting on those counts along with the course results. We need to have that count along with our Course so that we can report it and also order by it. For this we use a JOIN from the "course" table to our derived table. SQLAlchemy is smart enough to know to join on the "course_id" foreign key if we just call join():
courses = session.query(Course).join(most_rated_course_id_subquery).all()
then to get at the count, we need to add that to the columns returned by our subquery along with a label so we can refer to it:
most_rated_course_id_subquery = session.query(
Review.course_id,
func.count(Review.course_id).label("count")
).\
group_by(Review.course_id).\
having(func.count(Review.course_id) > 1).\
subquery()
courses = session.query(
Course, most_rated_course_id_subquery.c.count
).join(
most_rated_course_id_subquery
).order_by(
most_rated_course_id_subquery.c.count.desc()
).all()
A great article I like to point out to people about GROUP BY and this kind of query is SQL GROUP BY techniques which points out the common need for the "select from A join to (subquery of B with aggregate/GROUP BY)" pattern.