How to modify context for child fields in graphql-ruby? - ruby-on-rails

I have query like this:
query {
organizations {
id
name
itemA {
fieldA
fieldB
}
}
}
returns
"data": {
"organizations": [
{
"id": 123,
"name": "first org",
"itemA": {
"fieldA": "some value A",
"fieldB": "other value B",
}
},
{
"id": 321,
"name": "other org",
"itemA": {
"fieldA": "other value A",
"fieldB": "value B",
}
}
]
}
One user have access to multiple organizations, but with different access rights for each org.
I need to have organization.id when fieldA and fieldB are resolved to validate access.
I tried to use context.merge_scoped!(organiozation_id: org.id) in resolver for a field, that returns single org.
Looks like it do what I need, child fields received correct value in context but I'm not sure. There is no documentation for that method and for scoped_context in general.
Also, if scoped_context is what I need, how can I set it for a list of items?
UPD: sample query
query {
organizations { // I need to pass item of this list to resolver of ItemA
someModel{
otherModel {
itemA // access depened on organization`
}
}
}
}

Feature was documented in newer version:
https://graphql-ruby.org/queries/executing_queries.html#scoped-context

I'm not 100% sure I got your problem, but I think what you need should be "transparent" to GQL.
You need two things to correctly list "items" for an organization: 1. which organization and 2. who is asking:
# type organization
def itemA
object # this is 1, the organization, current node in the graph
.get_fields_accessible_by(context[:who_is_asking]) # this is requirement 2
end
As you can see, there seems not to be a reason to manipulate context at all. (Unless I missed the point completely, so feel free to amend your question to clarify).

Could you try :
context[:organisation] = object #set this value in your organisation model
access it in another model using, current[:organisation]
Additionally, you can create helper method
something like
def current_organisation
context[:current_organisation]
end
Thanks

Related

Returning Neo4j map projection with WebFlux

I have the nodes user and game with some relationships between them.
My REST API should return all relationships between the games and 1 user.
The cypher query i use is:
MATCH (u:User {id: '1234'} ) -[rel]- (game:Game) return game{.*, relationships: collect(DISTINCT rel)}
In my Neo4j Browser, everything works as expected and i see all properties i need.
But the GetMapping retuns everything except the relationship properties.
Neo4j Browser
{
"relationships": [
{
"identity": 54,
"start": 9,
"end": 8,
"type": "OWNED",
"properties": {
"ownedDate": "2021-07-03"
}
},
{
"identity": 45,
"start": 9,
"end": 8,
"type": "PLAYED",
"properties": {
"times": 5
}
}
],
"name": "Blood Rage",
"state": "ACTIVE",
"id": "1c152c91-4044-41f0-9208-0c436d6f6480",
"gameUrl": "https://asmodee.de/blood-rage"
}
GetMapping result (As you can see, the relationships are empty, but i have more empty JsonObjects, when there are more Relationships
{
"game": {
"relationships": [
{},
{}
],
"name": "Blood Rage",
"gameUrl": "https://asmodee.de/blood-rage",
"state": "ACTIVE",
"id": "1c152c91-4044-41f0-9208-0c436d6f6480"
}
}
The GetMapping is:
...
final ReactiveNeo4jClient client;
...
...
...
#GetMapping(value = { "/{id}/games"})
#RolesAllowed({"user", "admin"})
Flux<Map<String, Object>> findGamesByUser(#PathVariable String id){
String query = "MATCH (uuser:User {id: '" + id + "'} ) -[rel]- (game:Game) return game{.*, relationships: collect(DISTINCT rel)}";
return client.query(query).fetch().all();
}
A RelationshipProperty-Example
#RelationshipProperties
#Data
#Builder
public class PlayedGame {
#Id
#GeneratedValue
private Long relationshipId;
#Property
int times = 0;
#TargetNode private GameEntity game;
public int addPlay(){
this.times = this.times + 1;
return this.times;
}
}
What do i have to change in my GetMapping to show the relationship-properties?
Thank you,
Kevin
You need to return the actual nodes and relationships, otherwise you're missing the id-mapping.
There should be examples in the SDN docs.
Best if you have a small reproducible example (e.g. with the default movies graph).
Not sure if there is something off in your SDN setup, in general for such simple queries you should be able to just use a repository and not need to write cypher queries by hand.
The general information given by Michael is correct but there is more in you question:
First of all the meta domain model is completely ignored if you are using the Neo4jClient. It does not automatically map anything back but uses the driver's types.
As a result you will end up with an (current state of this answer) InternalRelationship which does not have any getter-methods.
I assume that you are serializing the result in the application with Jackson. This is the reason why you see objects that represent the relationships but without any content within.
If you want to get things mapped for you, create also the domain objects properly and use (at least) the Neo4jTemplate with your query.
If you model User, Game, and the relationship properties like PlayedGame correctly, a
neo4jTemplate.findAll("MATCH (u:User)<-[rel]-(g:Game) return u, collect(rel), collect(g)", User.class)
will map the results properly. Also if this is all you have, you could also skip the custom query at all and use
neo4jTemplate.findAll(User.class)
or
neo4jTemplate.findById(useId, User.class)

Searchkick: how to save records in ElasticSearch in different indices based on record timestamp?

I have a Rails Model with Searchkick.
I want my model instances to be saved in ElasticSearch in different indices based on the month creation of the instance.
Lets say I have the following instances in my Model:
A created the 03/25/2021
B created the 03/28/2021
C created the 04/01/2021
Instead of having one ES index (which is the default behavior for Searchkick), how can I store when my instances are created:
A & B in ES index labeled: model_2021_03
C in ES index labeled: model_2021_04
From what I understand, there are two main steps:
Create Multiple Index(indices)
Store the document in one of those index.
Idea here is making the index as "Write_Index" in which you want to put the document and mark others as "Read_Index".
So you can start with:
1. Creating an Index Template.
PUT /_index_template/model_template
{
"index_patterns": [
"model*"
],
"priority": 1,
"template": {
"aliases": {
"model":{}
},
"mappings": {
"dynamic":"strict",
"_source":
{"enabled": false},
"properties": {
//your filed mappings here
}
},
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 3
}
}
}
}
2.Create an index for a particular month,which will follow the model template(in step 1) with an naming strategy in your code
PUT model_YYYY_MM
Ex: lets say, you create two index model_2021_03, model_2021_04, now you want to store the documents in one of them,
Idea here is to mark the index, that you want to store the document in
as "Write_Index" and all other as "Read_Index", so when you store the
document using alias name("model") here, it will get stored in write
index by default.
3. Making the index as write index and others as read
POST /_aliases
{
"actions": [
{"add":
{"index": "model_2021_04",
"alias": "model",
"is_write_index": true}
},
{"add":
{"index": "model_2021_03",
"alias": "model",
"is_write_index": false}
}
]
}
4.Finally putting documents in index using alias name
PUT /model/_doc/1
{
//your data here
}

The ambiguous error occurs while using the models.sequelize.col () in the include in sequelize(node.js express)

mariadb,
show tables;
Board
Comment
my code,
models.Board.findAll({
attributes: [
'_no', 'title', 'content', 'createdAt'
],
include: [
{
model: models.Comment,
tableAlias: 'Comment',
attributes: [
[models.sequelize.fn('count', models.sequelize.col('_no')), 'comment']
]
}
],
group: ['_no', 'title', 'content', 'createdAt'],
order: [
['createdAt', 'DESC']
],
raw: true
}).then(function(boards)
{
res.send(JSON.stringify(boards));
});
Why error occurs?
Unhandled rejection SequelizeDatabaseError: ER_NON_UNIQ_ERROR: Column '_no' in field list is ambiguous
models.sequelize.col('_no') -> models.sequelize.col('models.Comment._no')
error, too.
models.sequelize.col ( '_ no') in the _no want to use Comment table.
thanks.
Appearently both Board and Comment have a _no column? In that case you need to specify which one you want to count, fx: models.sequelize.col('board._no')) (make sure the table name matches the pluralization and capitalization of the table in the rest of the query)
if multiple table is there in query then you need to specify which table createdAt you want to group by because node have all table createdAt(default created)
group: ["your_table_name_here\".\"createdAt"]
if we use multiple model for get record in that case same field name in 2 or more model then you need to specify which model record you want to group by so in that case i write group: ["your_table_name_here"."createdAt"]
Try to specify the model where createdAt is located
import { Parking } from "../database/models";
const parking = await Parking.findAndCountAll({
where: {
"$Parking.createdAt$": {
[Op.between]: [new Date(startDate), new Date(endDate)]
}
}
})

Firebase Security Rules: .indexOn unique ids

I have this structure:
"post": {
"groupMember": {
"-KHFHEHFWDB1213": "true",
"-KSJHDDJISIS011": "true",
"-KJSIO19229129k": "true"
}
}
I want to .indexOn the auto-generated unique groupMember ids.
I tried doing this:
"post": {
".indexOn": "groupMember"
...
}
But I'm still getting this error:
Consider adding ".indexOn": "groupMember/-KHFHEHFWDB1213" at /post
So how do I add a .indexOn on a unique id?
UPDATE:
This is the query I use (in Swift):
postRef.queryOrderedByChild("groupMember/\(uid)").queryEqualToValue(true).observeEventType(.Value, ... )
To query whether or not one of the given keys has value "true" (note that as typed your data structure is a string, not a boolean -- something to look out for!) you'll want to create security rules like so:
{
"post": {
"groupMember": {
"$memberId": {".indexOn": ".value"}
}
}
}
And then use queryOrderedByValue("true") on the /post/groupMember path. Important to note is $memberId in the rules, which declares a wildcard key representing your autogenerated ids, and .value, which indicates that rather than indexing on a child property (if your structure had another layer of nesting) you want to index on the immediate leaf node value.

Exclude fields from document in mongoid?

I have a Record model with many dynamic attributes. I want to make a request to the model an send the response as JSON to the client. But i want to exclude fields like _id and all foreign_keys in this model.
I found an interessting answer how to exclude the values of some keys: How do I exclude fields from an embedded document in Mongoid?, but the keys in the response still exists.
I got:
{
"_id": 1,
"name": "tom"
}
And the without method makes:
{
"_id": nil,
"name": "tom"
}
But i want:
{
"name": "tom"
}
Is it possible to remove or exclude some keys and the values from the result?
You don't want to remove fields from the mongoid document, what you want to do is remove fields from the generated json.
In your controller, do
render :json => #model.to_json(:except => :_id)
Documentation for the to_json method http://apidock.com/rails/ActiveRecord/Serialization/to_json
taken from the mongodb documentation at: http://docs.mongodb.org/manual/reference/method/db.collection.find/
Exclude Certain Fields from the Result Set
The following example selects documents that match a selection criteria and excludes a set of fields from the resulting documents:
db.products.find( { qty: { $gt: 25 } }, { _id: 0, qty: 0 } )
The query returns all the documents from the collection products where qty is greater than 25. The documents in the result set will contain all fields except the _id and qty fields, as in the following:
{ "item" : "pencil", "type" : "no.2" }
{ "item" : "bottle", "type" : "blue" }
{ "item" : "paper" }
i suppose mongoid is setting the _id attribute to nil since mongoid models have a defined set of attributes (even if they are dynamic, _id, _type etc are defined). maybe you can try it with the mongodb driver.
but i think RedXVII answer is the more practical way to go

Resources