Find in a collection based on an array in user's profile - javascript

Sorry if this is a basic question, I'm relatively new to javascript and Meteor.
I'm trying to create a recommended page that recommends sites that you have upvoted. It takes the tags that are on the post, and puts them into the user profile under 'tags' as an array.
var websiteTags = Websites.findOne(website_id, {fields: {tag: 1} });
var getTags = websiteTags.tag;
Meteor.users.update(this_user, {$addToSet: {"profile.tags": getTags}});
Then under the templates helper, I'm trying to return a list of websites that have the tags equal to what is in the users profiles.
Template.user_recommended_list.helpers({
websites:function(){
var usersTags = Meteor.user().profile.tags;
return Websites.find({tag: usersTags});
}
});
If I add an index number like: Meteor.user().profile.tags[0], it will work, but I need to query multiple user tags against the website tag list.
I've tried looping through the users tags then return each value to the page, but it wouldn't work. What's the best way to do it?
Thanks in advance

Just use the $in operator in your mongo query:
return Websites.find({tag: {$in: usersTags}});

Related

Filtering in join in supabase

Im using supabase with a database which have 2 tables (that are implicates in this issue).
Tables are teachers and users. Both have ID and id_teacher/id_user respectively.
Im working in a query where i need to get all teacher, joining in users table, where theres a image column.
I need just to get the teachers where the user have an not null image.
const query = supabase.from(`teachers`).select(
`
*,
id_user(
image
)
`
)
This query works to get teachers joining in users table. Because i get my wanted response.
This is a short example.
{
"id": 560,
"teacher_experience": 9,
"id_user":{
"image": "example-image.jpg"
}
}
The trouble is when i try to use some filter to avoid null images.
query.not('id_user.image', 'eq', null)
query.not('id_user.image', 'in', null)
query.ilike('id_user.image', 'null')
Are just an examples o filters tha i tryed for avoid the teachers which user.image have a null value.
Because, i want to NOT GET the entire item, but i get an item wiht a id_user = null
{
"id": 560,
"teacher_experience": 9,
"id_user": null // In this case image is null but still giving me the user
}
How is the correct form to solve this?
Just create a view in database for solve this problem. A view is a shortcut to queries and it possible apply where clause.
In sql editor on supabase https://app.supabase.io/project/{your_project_id}/editor/sql
create a new view with joins;
CREATE VIEW teachers_view AS
SELECT
t.*,
iu.image as image
FROM teachers as t
LEFT JOIN id_user as iu WHERE t.id = iu.teacher_id;
read more about left join here
and in application use
supabase.from('teachers_view').select().neq('image', null);
This has now been implemented with PostgREST 9!
Here's an example:
const { data, error } = await supabase
.from('messages')
.select('*, users!inner(*)')
.eq('users.username', 'Jane'
In your, case you'd have to do id_user!inner(image)
Source: https://supabase.com/blog/postgrest-9#resource-embedding-with-inner-joins
query.not("your_column_name", "is", "NULL")
worked for me!
odd enough, if you want to check for NULL
.filter("your_column_name", "is", "NULL")
seems to be the solution. No idea why it's not consistent
It is not possible atm.
You can see state of issue here.
Some posibilities are using views o start the query in the other table.
The Supabase client uses postgrest, so you can use all sorts of operators in your queries. See this page as a reference.
This feature came up recently with the release of the support for PostgREST 9. You have to use !inner keyword, you can now filter rows of the top-level table.
const query = supabase.from(`teachers`).select(
`
*,
id_user!inner(image)
`
).not("id_users.image", "is", "NULL")
you can try like with inner joins by using the !inner operator in select
const query = supabase.from(`teachers`).select(
`
*,
id_user!inner(
image
)
`
)

How to update a user's tags ? using Quickblox javascript SDK

How can i update a user' tags using Quickblox javascript SDK ?
i tried using the following parameter names :
user_tags
tags
using
var params = {
user_tags: ["testing"]
};
Please don't answer me with "you can use custom objects, etc.." i'm already using them for something else.
I want to use tags, and nothing else
As stated in the table on this page: http://quickblox.com/developers/Users#Update_API_User_by_identifier you should use tag_list key which accepts a comma separated list of tags.
QB.users.update(user_id, { tag_list: "tag1,tag2" }, callback);
Unfortunately QB docs aren't the best in the world...

Using Meteor publish-with-relations package where each join cannot use the _id field

I am working to solve a problem not dissimilar to the discussion present at the following blog post. This is wishing to publish two related data sets in Meteor, with a 'reactive join' on the server side.
https://www.discovermeteor.com/blog/reactive-joins-in-meteor/
Unfortunately for me, however, the related collection I wish to join to, will not be joined using the "_id" field, but using another field. Normally in mongo and meteor I would create a 'filter' block where I could specify this query. However, as far as I can tell in the PWR package, there is an implicit assumption to join on '_id'.
If you review the example given on the 'publish-with-relations' github page (see below) you can see that both posts and comments are being joined to the Meteor.users '_id' field. But what if we needed to join to the Meteor.users 'address' field ?
https://github.com/svasva/meteor-publish-with-relations
In the short term I have specified my query 'upside down' (as luckily I m able to use the _id field when doing a reverse join), but I suspect this will result in an inefficient query as the datasets grow, so would rather be able to do a join in the direction planned.
The two collections we are joining can be thought of as like a conversation topic/header record, and a conversation message collection (i.e. one entry in the collection for each message in the conversation).
The conversation topic in my solution is using the _id field to join, the conversation messages have a "conversationKey" field to join with.
The following call works, but this is querying from the messages to the conversation, instead of vice versa, which would be more natural.
Meteor.publishWithRelations({
handle: this,
collection: conversationMessages,
filter: { "conversationKey" : requestedKey },
options : {sort: {msgTime: -1}},
mappings: [{
//reverse: true,
key: 'conversationKey',
collection: conversationTopics,
filter: { startTime: { $gt : (new Date().getTime() - aLongTimeAgo ) } },
options: {
sort: { createdAt: -1 }
},
}]
});
Can you do a join without an _id?
No, not with PWR. Joining with a foreign key which is the id in another table/collection is nearly always how relational data is queried. PWR is making that assumption to reduce the complexity of an already tricky implementation.
How can this publish be improved?
You don't actually need a reactive join here because one query does not depend on the result of another. It would if each conversation topic held an array of conversation message ids. Because both collections can be queried independently, you can return an array of cursors instead:
Meteor.publish('conversations', function(requestedKey) {
check(requestedKey, String);
var aLongTimeAgo = 864000000;
var filter = {startTime: {$gt: new Date().getTime() - aLongTimeAgo}};
return [
conversationMessages.find({conversationKey: requestedKey}),
conversationTopics.find(requestedKey, {filter: filter})
];
});
Notes
Sorting in your publish function isn't useful unless you are using a limit.
Be sure to use a forked version of PWR like this one which includes Tom's memory leak fix.
Instead of conversationKey I would call it conversationTopicId to be more clear.
I think this could be now much easier solved with the reactive-publish package (I am one of authors). You can make any query now inside an autorun and then use the results of that to publish the query you want to push to the client. I would write you an example code, but I do not really understand what exactly do you need. For example, you mention you would like to limit topics, but you do not explain why would they be limited if you are providing requestedKey which is an ID of a document anyway? So only one result is available?

Mongoose: Adding an element to array

I'm using Drywall to create a website.
I'm trying to add a dashboard element to the accounts section of the admin site. The dashboard element is to store an array of dashboards (strings) that the user has access to.
I've managed to successfully add the "dashboards" into the schema and store data in it.
Here's the problem:
I need to be able to add elements to the array. The way the code stands currently replaces the contents of dashboards in the database.
I know I can use $addToSet, but I'm not sure how I'd do that since the fieldsToSet variable is sent to the findByIdAndUpdate() method as a single object.
Here's the snippet of my code:
workflow.on('patchAccount', function() {
var fieldsToSet = {
name: {
first: req.body.first,
middle: req.body.middle,
last: req.body.last,
full: req.body.first +' '+ req.body.last
},
company: req.body.company,
phone: req.body.phone,
zip: req.body.zip,
search: [
req.body.dashboards,
req.body.first,
req.body.middle,
req.body.last,
req.body.company,
req.body.phone,
req.body.zip,
]
};
req.app.db.models.Account.findByIdAndUpdate(req.params.id, fieldsToSet, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
workflow.outcome.account = account;
return workflow.emit('response');
});
});
Here's a link to the original file: (lines 184-203)
Thanks!
fieldsToSet is a bad name (at least misleading in this case), the parameter is actually update which can take $actions like $addToSet
I don't think you want to set (only) the search field with dashboards. I'm guessing that field is used to index users for a search. So you'll probably wind up doing something like this:
fieldsToSet = {
....all the regular stuff,
$addToSet: {dashboard: req.body.dashboardToAdd}
//I'm not sure that you can add multiple values at once
}
Since this is setting all of the values each time I'm not sure you actually will want to add single dashboard items. Instead you might want to get the full set of dashboards the user has and set the whole array again anyway (what if they removed one?)
fieldsToSet = {
....all the regular stuff,
dashboards: req.body.dashboards
//In this case you'd want to make sure dashboards is an appropriate array
}

I'm getting a "newItem() was not passed an identity for the new item" error while trying to add a new item to a JSON store

I've seen other posts in this site regarding the same issue and I've tried the solutions given. I've also visited the links that may offer a solution but I'm still stuck with the same error.
I'm using DOJO and something as simple as this won't even work
myStore.newItem({id: 'test', otherfield: 'otherinfohere'});
myStore.save();
Supposedly the "newItem() was not passed an identity for the new item" error appears when you haven't provided an identifier for the new item, which i have.
The whole purpose of this (Just in case anyone can provide a good idea or has done something similar before) is that i want to create a data grid that shows info from a particular store. The problem is, that in that store all the items may not have the same structure. For instance:
I may have a store that looks like this
{identifier: 'id',
label: 'name',
items: [
{ id:'1', name:'Ecuador', capital:'Quito' },
{ id:'2', name:'Egypt', capital:'Cairo' },
{ id:'3', name:'El Salvador', capital:'San Salvador' , additionalField: 'otherinfohere'},
{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', additionalField: 'otherinfohere'},
]}
This is possible because I'm the one constructing the store in a Spring Controller (I'm also using the Spring Framework) from information I have locally stored in a Berkeley DB. So what i need is a data grid with a dynamic layout because I don't want blank spaces to show in the view in the rows with lesser amount of fields, and i need to show all the info in the store at the same time, but i don't know how to do this.
I thought of doing it by creating a simple layout of only 1 field. In it I would load data from a store i create dynamically at runtime. The data in the store would be composed of HTML combined with the values coming from the original store so I could obtain something like this, which is inside an attribute of a JavaScript Object and let the browser parse it for me:
<div><span>id: originalID </span>....</div>
This of course is a simple example, the html layout i'm looking for is far more complicated, but i think that passing it as a string to an object might do the trick.
The problem is that i don't even know if that idea will work because i get that error whenever i try to add values to my secondary store.
rdb.modules.monitor.historicStore.fetch({onComplete: function(items, request){
for (var i = 0; i < items.length; i++){
var item = items[i];
var obj = new Object();
obj.id = rdb.modules.monitor.historicStore.getValue(item, "id");;
var html = "<div><span>";
html += rdb.modules.monitor.historicStore.getValue(item, "sql");
html += "</span></div>";
obj.html = html;
myStore.store.newItem(obj);
}
}});
In this context "historicStore" refers to the JSON store that has the values that i need to convert and add to "myStore" after i added some HTML.
I hope you got the main idea of what I'm trying to do. If anyone can help me we either of these problems i would really appreciate it. Thanks in advance
For the issue regarding store:-
"id" is mandatory for a store, if it is going to be used for a grid(datagrid, EnhancedGrid, etc. whatever). The items are handled only on basis of "id" attribute by the grid data structures.
Usually, id can be a loop variable/ auto incrementation, to avoid any cases like you have said. Before adding the store to the grid, ensure that all items have the id attribute. You can write a function which will loop through each item and check for this, else add an auto-incrementing value for the id attribute of that item.

Categories

Resources