Mongoose and sql comparison - sql

This is a multi question
From a mongoose result I have several items in the result which I get through result.length.
How can I get specific items e.g.
Person.find({'exployment.office':'Greenway'})
.exec(function(err, result){
//from the result, how can i get those items with
result.length would give me the number of items in the result
but how can i get a specific item without having to use loop to get
the specific item within the result
//There are like fifty people in the result,
//how can i get the number of items in result
});
In SQL, I have a query like this
select *
from table1, table2
where table2.field2 = value1
and table2.field2 = table1.field2
and table1.value1 = value3
e.g.
select *
from city, state
where state.name = 'xxy'
and state.id = city.state_id
and city.name != 'yyy'
How can this be converted to mongoose?
In SQL if I want to select people whose first name are e.g. Smith, Queen I can use things like
select *
from table
where first_name in (Smith, Queen)
This would give me result for people whose first_name matches SMith and Queen
How can I do this in mongoose?

select *
from Person
where first_name in (Smith, Queen)
Would simply be this using $in:
Person.find({'first_name': { $in: ['Smith', 'Queen']}}) ...
Next one:
select *
from city, state
where state.name = 'xxy'
and state.id = city.state_id
and city.name != 'yyy'
Using mongoose, you would need to use populate and create the schemas with ref relationships.
City.find({ "name": { $ne: "yyy"} }).populate({
"path": "state",
"match": { "state.name": "xxy" }
}) ...
Next one:
Person.find({'exployment.office':'Greenway'})
.exec(function(err, result){
//from the result, how can i get those items with
result.length would give me the number of items in the result
but how can i get a specific item without having to use loop to get
the specific item within the result
//There are like fifty people in the result,
//how can i get the number of items in result
});
You would filter as much as you can before you exec the query to get the records you need rather than filter after you get all in the result. result.length sure would give you the count although you could get the count via something like this;
Person.count({first_name: "Smith"}).exec() ...

Related

Add multiple rows in Laravel DB Query (for migrating WordPress usermeta table into new Laravel table)

I'm migrating Users from WordPress to Laravel. I want to join the users and user_meta tables. Then I will import into a new table.
In my user_meta table I have multiple rows assigned to the user_id. How do I import multiple rows with their own unique identifier.
Eg.
umeta_id = 1, user_id = 1, meta_key = first_name, meta_value = Bob
umeta_id = 2, user_id = 1, meta_key = last_name, meta_value = Builder
In the above example, I'd like to add first_name and last_name to the query output.
Then import into a new column in the Laravel DB (and stop using the user_meta reference table approach WordPress uses).
Here is my current query code and the output I get:
$wp_users = DB::connection('wordpress_db')
// ->select(DB::raw('um.meta_value as first_name'))
->select('um.meta_value as first_name')
->table('wp_users')
->leftJoin('wp_usermeta as um', function ($q) {
$q->on('um.user_id', '=', 'wp_users.id')
->where('um.meta_key', '=', "first_name");
})
->orderBy('wp_users.id');
and if i dump the output:
+"ID": 1
+"user_login": "123"
+"user_pass": "123"
+"user_nicename": "123"
+"user_email": "b#x"
+"user_url": "https://x"
+"user_registered": "2016-1-1 13:47:32"
+"user_activation_key": ""
+"user_status": 0
+"display_name": "Bobby Builds"
+"umeta_id": 222
+"user_id": 1
+"meta_key": "first_name"
+"meta_value": "Bob"
Rather than meta_value and meta_key I just want 'first_name' => 'bob' and then also the ability to do this for multiple values in the user_meta reference table
If I was writing RAW sql then I think I would approach this by having a left_join per value I want to get. I would then create an alias like
SELECT um1.meta_value as first_name
SELECT um2.meta_value as last_name
LEFTJOIN wp_usermeta as um1
LEFTJOIN wp_usermeta as um2
I've noodled around without luck - any ideas appreciated.
Thanks!
I've written about some of the processes involved here for further reference: http://raison.co/migrating-wordpress-users-to-laravel/
I did this in the end by using select to choose all columns from wp_users and then selectively adding the new joins.
See the code fixed code below:
$wp_users = DB::connection('wp_db')
->table('wp_users')
->leftJoin('wp_usermeta as um', function ($q) {
$q->on('um.user_id', '=', 'wp_users.id')
->where('um.meta_key', '=', "wbp_user_mob_phone");
})
->leftJoin('wp_usermeta as um2', function ($q) {
$q->on('um2.user_id', '=', 'wp_users.id')
->where('um2.meta_key', '=', "first_name");
})
->select('wp_users.*', 'um.meta_value as wbp_user_mob_phone', 'um2.meta_value as first_name')
->orderBy('wp_users.id');

Get multiple distinct values from query in Entity Framework

I'm running a query that will get results based on a location search and date. I have a geography column with location points (lat/long) that's indexed. When I search for an event on a date it searches for all events within a distance (radius) on that date.
The problem is that if there are, say 10 events, all at the same location on the same date, all 10 results will come back in the first page. I'd like to mix this up and only show 2-3 from each location to give the result set some variety, so the user doesn't just see all events from one location.
I know I can use distinct to only fetch one event from each location, but how would I use it to get me 2-3 distinct values?
Here is my query so far.
viewModel.Events = dbContext.YogaSpaceEvents
.Where(i => i.EventDateTime >= adjustedSearchDate &&
i.LocationPoints.Distance(location) <= radius)
.Distinct()
.OrderBy(i => i.EventDateTime)
.Select(i => new EventResult
{
//fill view model here
})
.ToPagedList(Page, 10);
I don't think there's a way to get EF to generate such a query, which for SQL Server would be something like this:
with q as
(
select *,
( row_number() over (partition by StateProvinceId order by CityID) -1 ) / 3 MyRanking
from Application.Cities
)
select CityId, CityName,StateProvinceID
from q
order by MyRanking, StateProvinceID, CityID
offset 10 rows
fetch next 20 rows only
Note that this example doesn't use distance. But the idea is identical: the first 3 cities in each state are returned first, then the next 3, etc.
Or you could fetch all the matching events and sort them in memory.
I think you should be able to do something like:
dbContext.YogaSpaceEvents
.Where(i => i.EventDateTime >= adjustedSearchDate &&
i.LocationPoints.Distance(location) <= radius)
.GroupBy(i => i.Geography)
.SelectMany(g => g.OrderBy(x => x.EventDateTime).Take(3))
.Select(i => new EventResult { //fill view model here })
.ToPagedList(Page, 10);

Group by query, each group has to not have any item not in a List

In need a query that will help me solve this.
Here's my table 'tags':
id (int)
name (String)
user_id (int)
hardware_id (int)
I am grouping the results of the 'tags' table by hardware_id. I also have a List of tags (List<string>).
I want to get the hardware Id of the groups that all of the tags in the custom List matches at a name in the table above.
In other words, I want to get the hardware_id's that the custom List tags matches their name's. There might be name's that doesn't have a match in the custom list, but all of the custom list tags, must be in the group, and if it satisfies this need, I can the Id of that group.
I found it hard to explain and I didn't get an answer for that. I thought about doing it with foreach because it was so hard to solve, but I couldn't do it either and it's very inefficient to do it that way.
Example:
List : ['tag1', 'tag2']
Table Rows:
1, tag1, 5, 1
2, tag2, 5, 1
3, tag3, 5, 1
4, tag4, 5, 2
5, tag5, 6, 2
In this case, I should get the hardware_id of 1, because although one of the hardware Id's have tag3, it doesn't have any rows with a tag name that isn't in the List. IF the List had 'tag4', the hardware_id = 1 WOULDN'T be returned, because the List has a tag that the hardware_id group doesn't have.
If the Group doesn't have an item that the List has, it won't appear in the final result.
Someone game me this code, but it didn't work:
List<decimal> matchingHardareIds = db.tags.GroupBy(x => x.hardware_id)
.Where(x => x.All(s => tags.Contains(s.name.ToLower()) || 0 == tags.Count() && (s.user_id == userId)))
.Select(x => x.Key).ToList();
In that query, when I have one tag in the List and in the table I have several items with hardware_id 1 and one of them has a 'name' that is equal to the value in the List it will return empty results. this is because the rows in the table for a specific group by hardware_id, has a row with a name that doesn't appear in the custom List.
I need a query in either Entity Framework or Linq. Thanks a lot.
Use this:
var t = db.tags.GroupBy(x => x.hardware_Id)
.Where(x => tags.All(y =>
x.Any(z=> z.name == y)))
.Select(x=>x.Key).ToList();
Can not provide you with the entity framework or linq query, but the sql solution is to count the matches like this:
SELECT hardware_id
FROM tags
WHERE name IN (<list>)
GROUP BY hardware_id
HAVING COUNT(DISTINCT name) = <listDistinctCount>
<listDistinctCount> is the count of distinct values in the list. Which you can prepare prior to the query.

SailsJS manually populate records using Model.query

lets say i have this example as my app
http://sailsjs.org/#!/documentation/concepts/ORM/Associations/OnetoMany.html
For some big reasons(complicated) I cannot use Model.populate() and I'm stuck in using Model.query()
Does anyone know how to get the result as User.find().populate('pets') Using Model.query() Please
Thank you
You can do it like waterline adapters do to populate OneToMany:
Retrieve parents : select * from user ...
Retrieve children for each parent in only one query to not overload DBMS:
select * from pet where user = user1.id union select * from
pet where user = user2.id union ... union select * from pet where user
= userN.id.
Regroup children by parentPk(you can use lodash or underscore.js functions to do it) Ex:
users.forEach(function(user){
user.pets = _.filter(pets,function(pet){
return pet.user === user.id;
});
});

Nhibernate - How do I get ordered distinct results with QueryOver?

public class City
{
virtual public long Id { get; set; }
virtual public string Name { get; set; }
}
City table contains duplicated Names and I want to remove duplicates. I also want the results to be ordered by Id.
First I thought about the following query.
select distinct Name from City order by Id;
But this breaks with 'ORDER BY items must appear in the select list if SELECT DISTINCT is specified.' exception. After seeing http://weblogs.sqlteam.com/jeffs/archive/2007/12/13/select-distinct-order-by-error.aspx I think I should do:
select Name from City group by Name order by min(Id)
So my question is how can I do this query with QueryOver?
This is possible in ICriteria:
var list =
session.CreateCriteria<City>()
.SetProjection(Projections.Group("Name"))
.AddOrder(Order.Asc(Projections.Min("Id")))
.List<string>();
But this is not currently possible in QueryOver, because the .OrderBy(IProjection) overload is missing. Once the missing overload has been added it should look something like:
var list =
s.QueryOver<City>()
.Select(Projections.Group<City>(p => p.Name))
.OrderBy(Projections.Min<City>(c => c.Id)).Asc
.List<string>();
Note that the Projections overloads are there just now, so you can write the following (typesafe) query in ICriteria:
var list =
session.CreateCriteria<City>()
.SetProjection(Projections.Group<City>(c => c.Name))
.AddOrder(Order.Asc(Projections.Min<City>(c => c.Id)))
.List<string>();
So, what I've found is pretty simple...
var query = session.QueryOver<MyModel>()
// Conditions here
.OrderBy(m => m.GetThisDistinctField).Desc() // ...or Asc()...
.SelectList(m => m.SelectGroup(g => g.GetThisDistinctField));
var result = query.List<FieldDataType>().ToList();
return result;
To get an ordered query in queryover, start with a query that includes whatever criteria you need, but then add the SelectList/SelectGroup setup in order to get the distinct list. In other words, it's sort of like NHibernate can take a regular query, and then do special stuff to make it a select distinct query.
This is a solution I'm using in a current project I'm working on; I hope it helps someone else too.