@michael_hoeller thanks for the warm welcome.
I read through the documentation and tried some ways, but the result was not what I wanted.
I program in Clojure with the Monger Library. So the Data I posted above has been stored in the collection “rights” as following documents:
{
"_id" : NumberLong(1),
"name" : "Hugo",
"rights" : []
},
{
"_id" : NumberLong(2),
"name" : "Hermann",
"rights" : [
{
"to" : NumberLong(1),
"type" : "write",
"level" : NumberLong(0)
}
]
},
{
"_id" : NumberLong(3),
"name" : "Mauer",
"rights" : [
{
"to" : NumberLong(1),
"type" : "write",
"level" : NumberLong(0)
},
{
"to" : NumberLong(2),
"type" : "read",
"level" : NumberLong(1)
}
]
},
{
"_id" : NumberLong(4),
"name" : "Jon",
"rights" : [
{
"to" : NumberLong(1),
"type" : "read",
"level" : NumberLong(1)
},
{
"to" : NumberLong(2),
"type" : "read",
"level" : NumberLong(1)
}
]
},
{
"_id" : NumberLong(5),
"name" : "Jane",
"rights" : [
{
"to" : NumberLong(1),
"type" : "write",
"level" : NumberLong(0)
},
{
"to" : NumberLong(3),
"type" : "write",
"level" : NumberLong(0)
},
{
"to" : NumberLong(6),
"type" : "read",
"level" : NumberLong(1)
},
{
"to" : NumberLong(4),
"type" : "read",
"level" : NumberLong(1)
}
]
},
{
"_id" : NumberLong(6),
"name" : "Michael",
"rights" : [
{
"to" : NumberLong(4),
"type" : "read",
"level" : NumberLong(1)
},
{
"to" : NumberLong(5),
"type" : "read",
"level" : NumberLong(1)
}
]
}
Foe the search I use following function:
(defn find-projected-graph [collection-name query & {:keys [depth as from-field to-field projection restrict-search-with-match]
:or {depth Integer/MAX_VALUE
from-field :parent
to-field :_id
restrict-search-with-match {}
projection nil
as "Ontology"}}]
(let [aggregation-array [{"$match" query}
{"$graphLookup" {:from collection-name
:startWith (str "$" (if (keyword? from-field) (name from-field) from-field))
:connectFromField from-field
:connectToField to-field
:as as
:maxDepth depth
:depthField "numConnections"
:restrictSearchWithMatch restrict-search-with-match
}}]]
(aggregate collection-name
(if (nil? projection)
aggregation-array
(conj aggregation-array {"$project" projection})))))
(Short notes: In the Map after :or
are the standard values defined. For example if I don’t define :to-field
the value “connectToField” is the field “_id”. And the key values with the : are the field names so :_id is “_id” and Strings like “rights.to” are translated normally.)
If I now use following calls
(find-projected-graph "rights"
{:name "Michael"} :from-field "rights.to" :restrict-search-with-match {"rights.type" "read"})
or
(find-projected-graph "rights"
{:name "Michael"} :from-field "rights.to" :restrict-search-with-match {"rights.level" {$gte 1}})
I get the following result:
({:_id 6,
:name "Michael",
:rights [{:to 4, :type "read", :level 1} {:to 5, :type "read", :level 1}],
:Ontology [{:_id 6,
:name "Michael",
:rights [{:to 4, :type "read", :level 1} {:to 5, :type "read", :level 1}],
:numConnections 1}
{:_id 3,
:name "Mauer",
:rights [{:to 1, :type "write", :level 0} {:to 2, :type "read", :level 1}],
:numConnections 1}
{:_id 5,
:name "Jane",
:rights [{:to 1, :type "write", :level 0}
{:to 3, :type "write", :level 0}
{:to 6, :type "read", :level 1}
{:to 4, :type "read", :level 1}],
:numConnections 0}
{:_id 4,
:name "Jon",
:rights [{:to 1, :type "read", :level 1} {:to 2, :type "read", :level 1}],
:numConnections 0}]})
But I missing “Hermann” because “Mauer” has a “read” right to “Hermann”.
I think it is because “restrictSearchWithMatch” is a filter which is performed after the traversal of the graph.
The question is, exists a way to specify that the $graphllokup-function only considers “rights” which have the “type” “read” to find the next connection?
For example if I have this document
{
"_id" : NumberLong(3),
"name" : "Mauer",
"rights" : [
{
"to" : NumberLong(1),
"type" : "write",
"level" : NumberLong(0)
},
{
"to" : NumberLong(2),
"type" : "read",
"level" : NumberLong(1)
}
]
I get the link to the document with _id 2 but the link to document with the _id 1 is ignored.
The reason I ask this, I try to simplify a right-service which handles read and write access to objects but the rights are distributed between person, groups, and subgroups.