Grouping ActiveRecord objects in batches - ruby-on-rails-3

I'm trying to return a group of products in my rails so that I can seperate them when I iterate in my view.
For example, if I have 13 products, I want the block in the view to put the first 7 on one row, break and put the next six on the next row (I'm using css to put a shelf under the products).
I've been experimenting with find_in_batches, but can't seem to get this to work (not even sure it's the appropriate method).
#shelves = Product.find_in_batches(:batch_size => 7) { |products| products }
I usually use group_by when I want to group based on a date, for example -- is there a way to use group_by to group by counts, instead of model attributes?

find_in_batches.map will give you a no block error. What you actually want is:
#shelves = Product.all.in_groups_of(7)
And if you'd like the last group to not have extra nil objects padding it out, try:
#shelves = Product.all.in_groups_of(7, false)
Of course, you'll want to replace all with a more sensible scope so you're not loading your entire list of database objects into memory :)

You want an array of batches. Just mapping over the batches should do it.
#shelves = Product.find_in_batches(:batch_size => 7).map{|batch| batch}

Related

Get common ManyToMany objects with django extra select

class Seller(object):
type = ...
name = ...
cars = models.ManyToManyField(Car)
class PotentialBuyer(object):
name = ...
cars = models.ManyToManyField(Car)
class Car(object):
extra_field = ...
extra_field2 = ...
Suppose I have a relationship like this. I would like to use extra queryset modifier to get the list of cars that are already been picked out by PotentialBuyers when I fetch a seller object. I suppose the query queryset will something like this.
def markPending(self)
return self.extra(select={'pending': 'select images from PotentialBuyer as t ...'})
How can I accomplish this? Is there a better way? I could fetch the seller object and the potential object and do sets, but I'd think it would be cleaner to make it handled by the database. I am using PostgreSQL 9.5.
I think the Exists subquery expression will do what you want. Or at least it'll get you started on the right path. Docs Or you might want to use an aggregate to count the number of them.
Edit: If you need to select the full objects rather than the count, existence or a single entity, then use a Prefetch instance in prefetch_related. https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.Prefetch
Not quite the answer, but this is the solution I ended up with and I am satisfied by the performance. Perhaps someone can answer the question later :
from api.models import PotentialBuyer
potentials = PotentialBuyer.objects.filter(owner=user_id, default=True).first().cars.all()
Car.objects.filter(....).annotate(pending=Case(When(id__in=potentials, then=Value(True)), default=Value(False), output_field=BooleanField()))

Cypher-Neo4j Node Single Property change to Array

Following is a Node we having in DB
P:Person { name:"xxx", skill:"Java" }
and after awhile, we would like to change the Skill to skill array, is it possible?
P:Person { name:"xxx", skill:["Java", "Javascript"] }
Which Cypher query should I use?
If you have a single skill value in skill, then just do
MATCH (p:Person)
WHERE HAS (p.skill)
SET p.skill=[p.skill]
If there are multiple values you need to convert to an array such as P:Person { name:"xxx", skill:"Java","JavaScript" } then this should work:
MATCH (p:P)
SET p.skill= split(p.skill,",")
In fact, I think your real problem here is not how to get an array property in a node, but how to store it. Your data model is wrong in my opinion, storign data as array in neo4j is not common, since you have relations to store multiple skills (in your example).
How to create your data model
With your question, I can already see that you have one User, and one User can have 1..n skills.
I guess that one day (maybe tomorrow) you will need to know which users are able to use Java, C++, PHP, and every othre skills.
So, Here you can already see that every skill should have its own node.
What is the correct model in this case?
I think that, still with only what you said in question, you should have something like this:
(:Person{name:"Foo"})-[:KNOWS]->(:Skill{name:"Bar"})
using such a data model, you can get every Skill known by a Person using this query:
MATCH (:Person{name:"Foo"})-[:KNOWS]->(skill:Skill)
RETURN skill //or skill.name if you just want the name
and you can also get every Person who knows a Skill using this:
MATCH (:Skill{name:"Bar"})<-[:KNOWS]-(person)
RETURN person //Or person.name if you just want the name
Keep in mind
Storing array values in properties should be the last option when you are using neo4j.
If a property can be found in multiple nodes, having the same value, you can create a node to store it, then you will be able to link it the other nodes using relations, and finding every node having the property X = Y will be easier.

Rails query the last of each type

I am using STI and have a table Widget that a bunch of other subclasses inherit from using STI. I want a query that gets the last created of each object with a uniq type.
I have a predefined array of types I want so lets say:
types = ["type1", "type2", "type3"]
So my query would be something like: (this doesnt work)
Widget.where(type: types).uniq.reverse
My goal is to get the last of each object that matches 1 of those types..
Not 100% sure, but something like this might work (untested):
ids = Thing.where(type: types).group(:type).maximum(:id).values
last_per_type = Thing.find(ids)
Thing.select("distinct type")
By the way, type is a special variable in rails and can't be used as a column name.

Adding items to a listview in a specific order

If Not m_Batchs Is Nothing Then
For Each Batch In m_Batchs
newListItem = lstWsJobs.Items.Add(Batch.Id.ToString)
With newListItem
.Name = Batch.Id.ToString()
.SubItems.Add(Batch.JobId.ToString)
.SubItems.Add(Batch.Complete.ToString)
.SubItems.Add(Batch.User)
.SubItems.Add(Batch.Time.ToString)
End With
Next
End If
I have this list view (which is working fine) and i want to find an efficient way of populating it in a specific order, ie by date, by identity etc.
I know i can use linq but as i understand this is inefficient. If m_batchs is a large list of objects then i will looping through this list many, many time (as linq behind the scenes loops through the object collection).
Any ideas?
LINQ is not inefficient in general but almost always it's easier to read and faster to implement, change and extend. Also, does it really matter if one approach is 1 millisecond faster on 1000 iterations?
So i assume that Batch is a custom type and m_Batchs is a List<Batch>:
// order by date
var query = m_Batchs.OrderBy(b => b.Time);
// order by identity
query = m_Batchs.OrderBy(b => b.ID);
// ...
Measure the difference between this simple LINQ query and your custom implementation.
Edit: Sorry, that was C#
Dim batchByTime = m_Batchs.OrderBy(Function(b) b.Time);
Dim batchByID = m_Batchs.OrderBy(Function(b) b.ID);

Get the last element of the list in Django

I have a model:
class List:
data = ...
previous = models.ForeignKey('List', related_name='r1')
obj = models.ForeignKey('Obj', related_name='nodes')
This is one direction list containing reference to some obj of Obj class. I can reverse relation and get some list's all elements refering to obj by:
obj.nodes
But how Can I get the very last node? Without using raw sql, genering as little SQL queries by django as can.
obj.nodes is a RelatedManager, not a list. As with any manager, you can get the last queried element by
obj.nodes.all().reverse()[0]
This makes sense anyway only if there is any default order defined on the Node's Meta class, because otherwise the semantic of 'reverse' don't make any sense. If you don't have any specified order, set it explicitly:
obj.nodes.order_by('-pk')[0]
len(obj.nodes)-1
should give you the index of the last element (counting from 0) of your list
so something like
obj.nodes[len(obj.nodes)-1]
should give the last element of the list
i'm not sure it's good for your case, just give it a try :)
I see this question is quite old, but in newer versions of Django there are first() and last() methods on querysets now.
Well, you just can use [-1] index and it will return last element from the list. Maybe this question are close to yours:
Getting the last element of a list in Python
for further reading, Django does not support negative indexing and using something like
obj.nodes.all()[-1]
will raise an error.
in newer versions of Django you can use last() function on queryset to get the last item of your list.
obj.nodes.last()
another approach is to use len() function to get the index of last item of a list
obj.nodes[len(obj.nodes)-1]