Display multiple fields of the same solr tag in Blacklight - solr

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

Related

How can I filter records by their ObjectID (_id) in Ag-grid

I'm using MongoDB to store my records and am using Ag-grid react to display them. The grid has several columns including the record's ObjectID (_id), name, type, etc. Using the filter agColumnTextFilter works for the name and type fields with the columnDef of:
{
headerName: 'Column Name',
field: 'name',
filter: 'agTextColumnFilter',
},
which then leads to this query setup (using the contains filter option):
case "contains":
qp[fieldName] = new RegExp(['.*', user input string, '.*'].join(''), 'ig');
this logs the correct query:
"query db { name: /.*query string.*/gi }"
and the proper rows are displayed. Since the displayed _id is a string as well I tried something similar:
{
headerName: 'ID',
field: '_id',
valueGetter: (params) => {
let id = params.data._id;
return id.slice(id.length-5); //only display last part of ID instead of entire thing
},
filter: 'agTextColumnFilter',
},
Using the same contains logic as above the following query is logged to the console:
query db { _id: /.*_id segment.*/gi }
However, no rows are returned in this case (even though there should be rows returned). Do I need to use different logic or is there a problem with this current logic? Any advice is appreciated.
Edit: Turns out even though the ID displays as a String a cast of the string to an ObjectID is needed:
qp[fieldName] = new ObjectID(_id string)
Problem with this is searching for part of a specific ID won't work because it's not a valid ID. Searching for a full ID works but isn't ideal either. If anyone has any ideas on how I can filter just part of the ID I'd appreciate it.
You can probably set a valueFormatter on the column that displays the partial ObjectId. The filtering will be done using the full ObjectId.

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

Customise select columns in ui-grid

Is it possible to put a custom column definition for select fields in a ui grid and pick up the rest of the fields from the data schema? This use case arises because my json data schema is variable and there's just one column I'm sure about(its presence in data) and would like to apply a custom cell template to just that column.
Grid options:
$scope.gridOptions = {
data: data,
columnDefs: [
{ field: 'name', width: 250, cellTemplate: "../../tpl/grid/name_template.html" }
]
}
where data is the json object of variable schema.
If I define the grid this way, only the name field from my data object will be displayed in the grid. Is it possible to use the custom column def for the name field and also display the other objects in the data object without specifying column definitions for them?
To provide more clarity:
my data object can be:
[{name: 'apple', type: 'fruit', seasonal: true}]
or:
[{name: 'apple', color: 'green', taste: 'sour'}]
Basically my use case is such that there's no way for me to know before hand what columns will be returned from the query that initialises the grid data object but I'm sure of the fact that a name column will be part of the data returned by the query. I would want to supply a custom cell template and other properties to the name field and also display the other columns that might be there.
The normal behaviour is that if I specify a column definition for one column in the field, then I have to specify definitions for all the other columns that are part of the data to make them visible and in my case I don't know what the other field names might be.
$scope.gridOptions = {
data: data,
columnDefs: [
{ field: 'name', width: 250, cellTemplate: $.get('url-to-your-template.html') }
]
}
Check if the above works. You can use your own service for fetching template

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

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] })})}

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