In RethinkDB using multi indexes for tags, how to get items that match more than one tag? - tagging

Suppose I have a story table (with example data):
story
{id: 1, name: 'First Story', tags: ['plants', 'flowers', 'dog']}
{id: 2, name: 'Second Story', tags: ['flowers', 'wedding']}
{id: 3, name: 'Third Story', tags: ['plants', 'wedding']}
The story table has a multi index on the tags field.
I can get all stories that have the plants tag with:
r.table('story').getAll('plants', {index: tags})
Now how would I get all stories that have both the plants and wedding tags in an effecient manner (hopefully utilizing the tags multi index)?
The use case requires user selectable filtering on an arbitrary number of arbitrary tags.

Passing multiple arguments to getAll finds the documents that match either tag:
r.table('story').getAll('plants', 'wedding', {index: 'tags'})
A simple multi-index on tags cannot be used to match all tags. A query that doesn't use an index would look like:
r.table('story').filter(r.row('tags').contains('plants','wedding'))
It might be possible to create and use a multi-index on the powerset of tags:
r.table('story').indexCreate('tags-powerset', r.row('tags').do(powerset), {multi:true})
r.table('story').getAll(['plants', 'wedding'], {index: 'tags'})
Because of restrictions of ReQL and in the interest of efficiency, the powerset function may need to be approximated, for example as:
function(tags) {
return tags.concatMap(function(a){
tags.map(function(b){
return [a,b] })})}

Related

Firestore many to many relationships - How to update data?

Like a note app, you can set tags to a note. Also, you can search notes with tag.
Here is the firestore structure:
notes(collection)
note_1(doc)
content: 'some words...'
tags: ['apple', 'banana']
tags(collection)
tag_1(doc)
name: 'apple'
tag_2(doc)
name: 'banana'
If I change tag_1.name to 'new_apple', how shold I update note_1.tags?
You're going to have to:
Query for all notes documents where the tags array contains "apple"
Iterate the documents in the result set. For each document:
Update update the tags array in memory to remove "apple" and add "new_apple"
Write the new tags array back to the document

create array for morris js in laravel

I have difficulty loading certain data from the table to get a json array and include it into the morris js donut (example: https://codepen.io/ncarlucci/pen/JYxQBK)
I want to load from the table subscriber the different names from the column type and count them to get the following array:
[
{value: 50, label: 'typename1'},
{value: 25, label: 'typename2'},
{value: 25, label: 'typename3'},
],
if I do it like this:
$subscriber = Subscribe::select('type')->get()->groupBy('type')
->map(function($subscribe){
return $subscribe->count();
})->toJson();
I get the follow output, but it is false:
{"company":1,"person":16,"user":6}
There might be a nicer way to handle your case, but since you didn't provide more informations about your model or database structure, this should work:
$subscriber = Subscribe::select('type')->get()
->groupBy('type')
->map(function($subscribe, $label) {
return ['value' => $subscribe->count(), 'label' => $label];
})
->values()
->toJson();
The key is to build the inner array element within the map function, then call values() to get rid of the unneded outer label left by the map function.
If you need further explaination, just ask in the comments below

Display multiple fields of the same solr tag in Blacklight

I have a solr index with nested fields in the form of
{ record: [
{ tag1: foo, tag2: bar }
]
}
The solr configuration cannot be changed, unfortunately.
In Blacklight, I want to display foo and bar separately under different fields, like so:
Tag1: foo
Tag2: bar
I was thinking I could just use config.add_index_field with a helper method to achieve this:
catalog_controller.rb
config.add_index_field 'record', label: 'Tag1', helper_method: :get_tag1
config.add_index_field 'record', label: 'Tag2', helper_method: :get_tag2
application_helper.rb
def get_tag1(options={})
options[:value][0]['tag1']
end
def get_tag2(options={})
options[:value][0]['tag2']
end
However, when doing so I get the error A index_field with the key record already exists.
Apparently, I can only add one index field per solr field at a time. How can I turn one such field into multiple fields in Blacklight?
Found the answer. I simply need to add the field variable to point to the same tag, that way I can change the original variable.
catalog_controller.rb
config.add_index_field 'record1', label: 'Tag1', field: 'record', helper_method: :get_tag1
config.add_index_field 'record2', label: 'Tag2', field: 'record', helper_method: :get_tag2

How to generate the right data structure for ngoptions in single request

I'm trying to return a data structure for an Angular screen with several dropdowns.
I don't want to make multiple requests to get the options for each select so I was hoping to create a single nested data structure in Django that contains all the options for each select (there are only a small number)
Angular wants something like this to use with the select and ngoptions directives:
{'booking_name': 'acme',
'current_sales_person': 2,
'sales_people_options': [
{id: 1, name: 'rod'},
{id: 2, name: 'jane'},
{id: 3, name: 'freddy'}
],
... lots more fields here ...
}
sales_people_options would populate the options for the dropdown and current_sales_person indicates which salesperson is initially selected.
How can I get Django Rest Framework to return this in a single request from a ModelSerializer?
I could just create the JSON directly via JSONRenderer but I've got a lot of other fields so I'm keen to use ModelSerializer.
The only way seems to be to add a method called sales_people_options to my Model.
However - I've got several of these fields to generate and it seems very wrong to add model methods for something that I only need for one specific serializer.
EDIT - I think I might need to subclass serializer.Field and override a method (probably field_to_native).
This is just a json object. The Django rest framework is capable of returning json strings which you can then JSON.stringify the string returned to turn it into an object angular is expecting.
{'booking_name': 'acme',
'current_sales_person': 2,
'sales_people_options': [
{id: 1, name: 'rod'},
{id: 2, name: 'jane'},
{id: 3, name: 'freddy'}
Checkout the Django JSON renderer; http://www.django-rest-framework.org/api-guide/renderers
This might be a weird way to do it but it worked:
class BookingSerializer(serializers.ModelSerializer):
class UserOptionsField(serializers.Field):
def field_to_native(self, obj, field_name):
return User.objects.all().values('id', 'username')
sales_people_options = UserOptionsField()
class Meta:
model = Booking
fields = (
'id', 'booking_no', 'current_salesperson', 'sales_people_options',
)
EDIT: And here's a generic solution:
class ModelOptionsField(serializers.Field):
def __init__(self, source=None, label=None, help_text=None, queryset=None, fields=None):
self.queryset = queryset
self.fields = fields
super(ModelOptionsField, self).__init__(source, label, help_text)
def field_to_native(self, obj, field_name):
return self.queryset.values(*self.fields)
that you use like this:
class MySerializer(serializers.ModelSerializer):
my_options_list = ModelOptionsField(queryset=User.objects.all(), fields=('id', 'username'))

MongoDB: Query and retrieve objects inside embedded array?

Let's say I have the following document schema in a collection called 'users':
{
name: 'John',
items: [ {}, {}, {}, ... ]
}
The 'items' array contains objects in the following format:
{
item_id: "1234",
name: "some item"
}
Each user can have multiple items embedded in the 'items' array.
Now, I want to be able to fetch an item by an item_id for a given user.
For example, I want to get the item with id "1234" that belong to the user with name "John".
Can I do this with mongoDB? I'd like to utilize its powerful array indexing, but I'm not sure if you can run queries on embedded arrays and return objects from the array instead of the document that contains it.
I know I can fetch users that have a certain item using {users.items.item_id: "1234"}. But I want to fetch the actual item from the array, not the user.
Alternatively, is there maybe a better way to organize this data so that I can easily get what I want? I'm still fairly new to mongodb.
Thanks for any help or advice you can provide.
The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :
db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })
You will have :
{
name: "John",
items:
[
{
item_id: "1234",
name: "some item"
}
]
}
See Documentation of $elemMatch
There are a couple of things to note about this:
1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.
2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.
In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.
3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.
4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.
If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).
If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.
A sample document might look like this:
{
_id: {user_id: ObjectId, item_id: "1234"},
name: "some item"
}
Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).

Resources