Can Mongoid `any_of` include use of external document relationships? - ruby-on-rails-3

I'm using MongoDB with Mongoid and trying to put in place a rudimentary search as a placeholder before we look at weighting, etc. The any_of method seems to be finding my embedded documents but not those linked by relations. Does anyone know if any_of can include relationships to other documents in the db, and if so what the syntax would be?
belongs_to :principal #owner
belongs_to :account #owner
scope :search, ->(text) { any_of(
{:description => /#{text}/i},
{:name => /#{text}/i},
{"entries.title" => /#{text}/i},
{"entries.description" => /#{text}/i},
{:tags => /#{text}/i},
{"account.name" => /#{text}/i}, # Not finding by account name - because account isn't embedded?
{"principal.name" => /#{text}/i} # Not finding by principal name - because not embedded?
)}

No, any_of is the equivalent of a MongoDB $or query, so the native MongoDB would be something like:
db.collection.find(
{ "text" :
{ "$or" :
[ { "account.name" => /#{text}/i }, { "principal.name" => /#{text}/i } ]
}
})
Mongo queries only run over a single collection, so to resolve the account.name and principal.name fields they'd need to be embedded inside the document, e.g.
{
text:
{
description: "...",
name: "...",
account: { name: "..." },
principal: { name: "..." }
}
}

Related

Logstash sprintf formatting for elasticsearch output plugin not working

I am having trouble using sprintf to reference the event fields in the elasticsearch output plugin and I'm not sure why. Below is the event received from Filebeat and sent to Elasticsearch after filtering is complete:
{
"beat" => {
"hostname" => "ca86fed16953",
"name" => "ca86fed16953",
"version" => "6.5.1"
},
"#timestamp" => 2018-12-02T05:13:21.879Z,
"host" => {
"name" => "ca86fed16953"
},
"tags" => [
[0] "beats_input_codec_plain_applied",
[1] "_grokparsefailure"
],
"fields" => {
"env" => "DEV"
},
"source" => "/usr/share/filebeat/dockerlogs/logstash_DEV.log",
"#version" => "1",
"prospector" => {
"type" => "log"
},
"bgp_id" => "42313900",
"message" => "{<some message here>}",
"offset" => 1440990627,
"input" => {
"type" => "log"
},
"docker" => {
"container" => {
"id" => "logstash_DEV.log"
}
}
}
I am trying to index the files this based on filebeat's environment. Here is my config file:
input {
http { }
beats {
port => 5044
}
}
filter {
grok {
patterns_dir => ["/usr/share/logstash/pipeline/patterns"]
break_on_match => false
match => { "message" => ["%{RUBY_LOGGER}"]
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "%{[fields][env]}-%{+yyyy.MM.dd}"
}
stdout { codec => rubydebug }
}
I would think the referenced event fields would have already been populated by the time it reaches the elasticsearch output plugin. However, on the kibana end, it doesnt not register the formatted index. Instead, its since like this:
What have I done wrong?
In Elasticsearch Output plugin docs:
https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html#plugins-outputs-elasticsearch-manage_template
Should you require support for other index names, or would like to
change the mappings in the template in general, a custom template can
be specified by setting template to the path of a template file.
Setting manage_template to false disables this feature. If you require
more control over template creation, (e.g. creating indices
dynamically based on field names) you should set manage_template to
false and use the REST API to apply your templates manually.
By default, elasticsearch requires you to specify a custom template if using different index names other than logstash-%{+YYYY.MM.dd}. To disable, we need to include the manage_template => false key.
So with this new set of info, the working config should be:
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "%{[fields][env]}-%{+yyyy.MM.dd}"
manage_template => false
}
stdout { codec => rubydebug }
}

Standalone rbac setup for module yii2

I`ve got two modules in my yii2-basic application. For common users I have "user" table and for superadmin users I have the second "superadmin" table. There are two users with different sessions in my app - users and superadmins. I need to use different, standalone rbac for superadmin users table. Is it possible to setup two different rbacs in two modules? Now it is setup in web.php file globally. Maybe it is possible somehow to setup authManager in module separately, not in global web.php file?
Thanks in advance!
I figured it out! In your module.php file specify authManager with different table names, you are supposed to create them before. You also can specify rbac submodule of mdm\admin if you want to use it as well. Specify there another usertable - SuperAdmin in the code below.
public function init()
{
parent::init();
$this->modules = [
'rbac' => [
'class' => 'mdm\admin\Module',
'controllerMap' => [
'assignment' => [
'class' => 'mdm\admin\controllers\AssignmentController',
'userClassName' => 'app\models\SuperAdmin',
'idField' => 'id',
'usernameField' => 'username',
],
],
'layout' => 'left-menu',
'mainLayout' => '#app/views/layouts/rbac.php',
],
];
$config = [
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
'itemTable' => 'superadmin_auth_item',
'assignmentTable' => 'superadmin_auth_assignment',
'itemChildTable' => 'superadmin_auth_item_child',
'ruleTable' => 'superadmin_auth_rule',
],
],
'as access' => [
'class' => 'app\components\SuperAdminAccessControl',//your overridden AccessControl class
'allowActions' => [
'admin/rbac/*',
'admin/default/login',
'admin/default/logout',
]
],
];
\Yii::$app->authManager->itemTable = 'superadmin_auth_item';
\Yii::$app->authManager->assignmentTable = 'superadmin_auth_assignment';
\Yii::$app->authManager->itemChildTable = 'superadmin_auth_item_child';
\Yii::$app->authManager->ruleTable = 'superadmin_auth_rule';
\Yii::configure(\Yii::$app, $config);
}
Overridden AccessControl class:
namespace app\components;
class SuperAdminAccessControl extends \mdm\admin\components\AccessControl
{
function __construct() {
$this->setUser('superadmin');//table name
}
}

Rails 3 parent and child association scopes optimization

I have a parent has many children association in my project. I'm trying to get a list of children that have certain flags set from the parent when I render it.
For example this:
# some_controller
#thread = Thread.includes(:posts)
render :json => #thread.posts.as_json
will return something like
[
{
"id" => 1,
"posts" => [
{ "id" => 1, "flagged" => true },
{ "id" => 2, "flagged" => false }
]
}
]
I'm trying to get the output to be like this
[
{
"id" => 1,
"posts" => [
{ "id" => 2, "flagged" => false }
]
}
]
i.e.: only posts that are not flagged should be rendered.
I've overridden the as_json method in my model in order to do this as such:
def as_json(options = {})
...
{
:id => self.id,
:posts => self.posts
}
...
end
I realize that I can define a scope in the Posts model and use :posts => self.posts.not_flagged, but this causes an extra database query for every thread in my database (makes everything slow).
Aside from a default_scope on the Posts model how else could I solve this extra query problem?
I figured it out a bit after I posted.
I can add a scope in my Parent model to do this:
# Thread.rb
...
has_many :unflagged_posts, :class_name => "Post", :conditions => { :flagged => false }
...
And in my controller:
# some_controller
#threads = Thread.includes(:unflagged_posts)
This way ActiveRecord eager loads the posts with the flagged condition, rather than doing an extra query for each post!

Laravel adding/finding relationships for relationships

How to find relationships for relationships with Eloquent ORM? Currently I have something like this. Simple relationship. I can find Image and it's photographer. Now I need to do something more complex, I need to find also photographers tags.
dump looks like this
object(Image) {
["attributes"] => [],
["relationships"] =>
["photographer"] =>
["attributes"] => [],
["relationships"] =>
}
But I need to add tags relationship so It would look like this
object(Image) {
["attributes"] => [],
["relationships"] =>
["photographer"] =>
["attributes"] => [],
["relationships"] =>
["tags"] =>
["attributes"] => [],
["relationships"] =>
}
How is that possible?
/Image model
public function photographer()
{
return $this->belongs_to('Photographer');
}
public function tags()
{
return $this->has_many_and_belongs_to('Tag', 'tag_relationships');
}
/Controller
$images = Image::with(['photographer'])->order_by('updated_at', 'desc')->get();
you just use laravel's dot syntax:
Image::with(['photographer', 'photographer.tags', 'photographer.tags.categories]) ....

Lookback API: How long is a defect in a particular state?

We have a state in our defects called "Need More Information". I would like to create a graph over time of how many defects are in that state at any particular period of time.
I think I can get the info to do that with the Lookback API with the following query:
my $find = {
State => 'Need More Information',
'_PreviousValues.State' => {'$ne' => 'Need More Information'},
_TypeHierarchy => -51006, # defect
_ValidFrom => {
'$gte' => '2012-09-01TZ',
'$lt' => '2012-10-23TZ',
}
I thought that would give me back a list of all defect snapshots where the defect was transitioning into "Need More Information" state, but it does not (seems to list everything that was ever in "Need More Information" state.
Technically what I need is a query that lists snapshots of any defects transitioning either TO OR FROM the "Need More Information" state, but since this simpler one did not seem to work as I expected, I thought I would ask first why the query above did not work the way I expected.
The "Generated Query" in the header that comes back is:
'fields' => 1,
'skip' => 0,
'limit' => 100,
'find' => {
'_TypeHierarchy' => -51006,
'_ValidFrom' => {
'$gte' => '2012-09-01T00:00:00.000Z',
'$lt' => '2012-10-23T00:00:00.000Z'
},
'_PreviousValues.State' => {
'$in' => [
undef,
5792599066,
5792599067,
5792599065,
5792599070,
5792599071,
5792599068,
5792599073,
5792599072,
5792599075,
5792599077,
5792599076,
5792599078,
3631859989,
3631859988,
3631859987,
3631859986
]
},
'State' => {
'$in' => [
4384150044
]
}
}
};
I tried leveraging the $nin clause and had success with it. You might try adjusting your query to resemble something like this:
find: {
_Type: 'Defect',
State: 'Need More Information',
'_PreviousValues.State': {
$in: [
'Submitted', 'Open', 'Fixed', 'Closed'
]
},
etc...
}