Triple join in CouchDB? - join

I have three type of documents:
Question
User - contains a source field
Answer - contains the corresponding question ID and user ID
Each questions is answered by multiple users and each user answers each question only once. I want to find for every question how many answers are there answered by users of source "source1".

I think that the nearer that you can arrive to what you want is the following (using Linked documents).
Suppose you have
{ "_id": "user1", "source": "source1" },
{ "_id": "user2", "source": "source2" },
{ "_id": "answer1", "question": "question1", "user": "user1" },
{ "_id": "answer2", "question": "question1", "user": "user2" }
and you define the following view
function(doc) {
if (doc.question) {
emit(doc.question, {_id: doc.user});
}
}
Then if you query that view with key="question1" and with include_docs=true
it will show you all the answers to question1 with all the user information, and you will only have to select those with source = "source1".
For example, with the previous values it will return:
{"total_rows":2,"offset":0,"rows":[
{"id":"answer1","key":"question1","value":{"_id":"user1"},"doc":{"_id":"user1","_rev":"1-c99dc8987841c25c72081a84252793a0","source":"source1"}},
{"id":"answer2","key":"question1","value":{"_id":"user2"},"doc":{"_id":"user2","_rev":"1-0d44e9f4d3806fb932b1b4fcb1e1507b","source":"source2"}}
]}
But AFAIK, what you cannot do in the map function of a view is to use information from other documents.

you can't achieve this within couchdb and need to use thirt-party modules.
for example that one:
sites.google.com/site/nosqldatajoiner/
or google nosql datajoiner

Related

Microsoft Graph - Education APIs - Students/Teacher Relationships [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
We are using Microsoft Graph API in an education context to store data about students that have been created by teachers. We are trying to figure out a way of being able to determine:
If a user is a student or a teacher. Based on documentation it seems this should be possible, but based on the comments on Stack Overflow and what we´ve seen, this only works if the school uses SDS and if we use Application, not Delegated permissions.
We want to determine somehow if a pupil is taught by a teacher. We can´t see any clear way we can do this. The only way we can figure something out is to scan through all the classes of the pupil and then find those classes where the user is an owner/teaches those classes.
You don't technically need to be using School Data Sync (SDS), but it does make the data a bit easier to work with and more consistent. This is because SDS will automatically populate the primaryRole, teacher, and student data each time it syncs. Without SDS, this would need to be determined and updated by your application. This is often a non-trivial exercise.
That said, there are a few ways to determine if a User is a Student or a Teacher without relying on the primaryRole. The more direct way is the /taughtClasses endpoint. This will return a collection of Classes that a User owns/teaches:
GET beta/education/users/{id|userPrincipalName}/taughtClasses
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.educationClass)",
"value": [
{
"id": "c4c1b1e9-bd8e-4ffc-acb4-e7745342bf6d",
"description": "PrimaryTestClass",
"displayName": "PrimaryTestClass",
"mailNickname": "PrimaryTestClass",
"classCode": "21001",
"externalName": "PrimaryTestClass",
"externalId": "21001",
"externalSource": "sis",
"term": {
"externalId": "12000",
"startDate": "2017-07-01",
"endDate": "2018-06-30",
"displayName": "SY1516"
},
"course": {
"subject": "PrimaryTestClass",
"courseNumber": "101",
"description": "PrimaryTestClass",
"displayName": "PrimaryTestClass",
"externalId": "21001"
}
},
{
"id": "8a15c9c0-13ed-464a-81ec-a6fb2d571599",
"description": "Health Level 1",
"displayName": "Health 1",
"mailNickname": "fineartschool.net",
"externalSource": "sis",
"externalName": "Health Level 1",
"externalId": "11019",
"classCode": "Health 501",
"createdBy": {
"application": {
"id": "a0c464d5-af1f-4bb9-bbdd-196bd577c796"
},
"user": {
"id": "7cea8be3-ceec-4200-b224-4845c8e38363"
}
}
}
]
}
Determining which Students are taught by which Teacher is trickier. You can get the list of Classes they belong to using beta/education/users/{id}/classes but you would then need to iterate over that list to get the list of Teachers for each Class by querying beta/education/classes/c4c1b1e9-bd8e-4ffc-acb4-e7745342bf6d/teachers?$select=id,userPrincipalName to compile the complete list of Teachers.
As for Application vs Delegated, the Education APIs are intentionally very restrictive when it comes to Delegated scopes. This is due to the intensely sensitive nature of Student information and the understandable level of security scrutiny this data receives.

Complex queries in CouchDB across multiple types of documents

I'm relatively new to CouchDB (more specifically Cloudant if it matters) and I'm having a hard time wrapping my head around something.
Assume the following (simplified) document examples:
{ "docType": "school", "_id": "school1", "state": "CA" }
{ "docType": "teacher", "_id": "teacher1", "age": "40", "school": "school1" }
I want to find all the teachers aged $age (eg. 40) in state $state (eg. CA).
Views only consider one document at a time; that is queries can't directly combine data from different documents. You can query across multiple fields in the same document using Cloudant Query. You can write a selector directly in the Cloudant dashboard. Something like
"selector": {
"age": {
"$gte": 40
},
"state": {
"$eq": "CA"
}
}
See https://cloud.ibm.com/docs/services/Cloudant/tutorials?topic=cloudant-creating-an-ibm-cloudant-query
with the full reference here: https://cloud.ibm.com/docs/services/Cloudant/tutorials?topic=cloudant-query
You could also use a so-called linked document to emulate basic joins, as outlined in the CouchDB docs https://docs.couchdb.org/en/stable/ddocs/views/joins.html

Join two nodes in Firebase

I'm working on an app, which is supposed to show data from two nodes(Firebase). Firebase DB is structured as:
{
"College": {
"4F2EAB65": {
"id": "4F2EAB65",
"name": "SomeCollege"
},
"A3C2ED31": {
"id": "A3C2ED31",
"name": "OtherCollege"
},
"F967B5A0": {
"id": "F967B5A0",
"name": "CoolCollege"
}
},
"Student": {
"3E20545B": {
"college-ID": "4F2EAB65",
"id": "3E20545B",
"name": "A"
},
"6FDEE194": {
"college-ID": "F967B5A0",
"id": "6FDEE194",
"name": "B"
}
}
I want to fetch student details having details: "id", "name", "college-ID", "college-Name"(Need to fetch "college-Name" by "college-ID").
I've achieved this using for loop at front end. Is there any way to get this achieved at Firebase server, also can we make something like join (SQL).
Thanks.
There is no support for server-side joins in the Firebase Realtime Database. Client-side joins are quite normal.
The alternative is to duplicate the data upon writing, so that you don't have to read from two locations.
What's best for your application is a matter of personal preference, your comfort level with the code involved vs data duplication, and the use-cases of your app.
Client-side jons are likely not as slow as you may think. See http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786

return certain fields first in elastic search

I have a Rails application with term => definitions stored in nodes on Neo4j that I want my users to search using elastic search. Through usage we've found they far more commonly want to find the term name first before they want to search the description. But I'm having trouble finding the function that returns results for a certain field first over other fields.
[
{
"id": 1,
"data": {
"name": "Foo",
"description": "Something super awesome."
}
},
{
"id": 2,
"data": {
"name": "Bar",
"description": "Something that depends on Foo"
}
}
]
search for "Foo"
Because both terms contain the word Foo in either name or description, my app returns both in alphabetical order and since Bar is alphabetically before Foo, Bar appears first. This can get very tiring when my users search for a common term used in many other terms.
How do I return results from the name field first followed by the secondary results in the description?
I have a feeling this has more to do with neo4j than elastic search
Its possible by Adding term and fields frequency value to your type mapping. http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/scoring-theory.html
name": {
"type": "string",
"store": true,
"norms": {
"enabled": false
},
"index_options": "docs"
}
let me known any queries.

Solr CollapsingQParserPlugin with group.facet=on style facet counts

I have a Solr index of about 5 million documents at 8GB using Solr 4.7.0. I require grouping in Solr, but find it to be too slow. Here is the group configuration:
group=on
group.facet=on
group.field=workId
group.ngroups=on
The machine has ample memory at 24GB and 4GB is allocated to Solr itself. Queries are generally taking about 1200ms compared to 90ms when grouping is turned off.
I ran across a plugin called CollapsingQParserPlugin which uses a filter query to remove all but one of a group.
fq={!collapse field=workId}
It's designed for indexes that have a lot of unique groups. I have about 3.8 million. This approach is much much faster at about 120ms. It's a beautiful solution for me except for one thing. Because it filters out other members of the group, only facets from the representative document are counted. For instance, if I have the following three documents:
"docs": [
{
"id": "1",
"workId": "abc",
"type": "book"
},
{
"id": "2",
"workId": "abc",
"type": "ebook"
},
{
"id": "3",
"workId": "abc",
"type": "ebook"
}
]
once collapsed, only the top one shows up in the results. Because the other two get filtered out, the facet counts look like
"type": ["book":1]
instead of
"type": ["book":1, "ebook":1]
Is there a way to get group.facet counts using the collapse filter query?
According to Yonik Seeley, the correct group facet counts can be gathered using the JSON Facet API. His comments can be found at:
https://issues.apache.org/jira/browse/SOLR-7036?focusedCommentId=15601789&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-15601789
I tested out his method and it works great. I still use the CollapsingQParserPlugin to collapse the results, but I exclude the filter when counting up the facets like so:
fq={!tag=workId}{!collapse field=workId}
json.facet={
type: {
type: terms,
field: type,
facet: {
workCount: "unique(workId)"
},
domain: {
excludeTags: [workId]
}
}
}
And the result:
{
"facets": {
"count": 3,
"type": {
"buckets": [
{
"val": "ebook",
"count": 2,
"workCount": 1
},
{
"val": "book",
"count": 1,
"workCount": 1
}
]
}
}
}
I was unable to find a way to do this with Solr or plugin configurations, so I developed a work around to effectively create group facet counts while still using the CollapsingQParserPlugin.
I do this by making a duplicate of the fields I'll be faceting on and making sure all facet values for the entire group are in each document like so:
"docs": [
{
"id": "1",
"workId": "abc",
"type": "book",
"facetType": [
"book",
"ebook"
]
},
{
"id": "2",
"workId": "abc",
"type": "ebook",
"facetType": [
"book",
"ebook"
]
},
{
"id": "3",
"workId": "abc",
"type": "ebook",
"facetType": [
"book",
"ebook"
]
}
]
When I ask Solr to generate facet counts, I use the new field:
facet.field=facetType
This ensures that all facet values are accounted for and that the counts represent groups. But when I use a filter query, I revert back to using the old field:
fq=type:book
This way the correct document is chosen to represent the group.
I know this is a dirty, complex way to make it work, but it does work and that's what I needed. Also it requires the ability to query your documents before insertion into Solr, which calls for some development. If anyone has a simpler solution I would still love to hear it.

Resources