How to access CouchDB documents using CouchRest model - ruby-on-rails

Please help me to solve this. I’ve around 1500 documents in my CouchDB, each document belongs to any one of the types (‘Survey’ and ’Response’).
I need solution for followings
1] Need to display Document Ids (_id) in a Dropdown list which has document type (documentType) as ‘Survey’
2] If I select an item (_id) from drop down, I need to display all document Ids (_id) in list box which belongs to selected ID (_id selected from drop down list)
I've total 1500 documents like this
{
"_id": "ff2fb2554682ba613c2f83c63502808a",
"_rev": "4-dd559696434a402739e789ccc8c9a481",
"answers": [
{
"answers": [
"Aug 19,2011"
],
"questionId": "50f3df434ae02ac7fff48c1c2bde83e4"
},
{
"answers": [
"Bechu Yadav"
],
"questionId": "15504f006e58872fd94871fe0c9d32ad"
},
{
"answers": [
"35"
],
"questionId": "3c447a2f5cc6ca1985ce2c81463a3c47"
},
{
"answers": [
"Male"
],
"questionId": "a6df7c25602939554612ef6de762f5b9"
},
{
"questionId": "2f66155965e60094f23f01af531d5af1",
"subAnswers": [
{
"questionId": "1dae2d86eef846c967254c9e369170ce"
},
{
"questionId": "40ffeb4d33dab1fe8d2d8b73c02ed13b"
},
{
"questionId": "2db1e8b6e97d5baa8935b9b31fcc9648"
},
{
"questionId": "0f8bb9f91ea8085b4ffb839ee8deabb5"
},
{
"questionId": "22a93ecb72c50ff8899f8b2937776e51"
},
{
"questionId": "e5106384790c2be745c952c4b867a0ff"
}
]
"questionId": "492cf9bd41257ea478c5222fbba06616"
}
],
"createdAt": "2011-08-19T21:05:36.486+0000",
"createdBy": "user4",
"documentType": "Response",
"ipAddress": "42.110.85.67",
"location": {
"latitude": 26.8415613,
"longitude": 75.8222883,
"provider": "network"
},
"surveyId": "6df022f0f371752167ad4920b38e1c37",
"published": true
}
And my CouchRest model looks like as follows
class Android < CouchRest::Model::Base
property :description, String
property :_id, String
property :_rev, String
property :documentType, String
design do
view :by_documentType,:map =>"function(doc){if (doc.documentType == 'Survey') {emit(doc._id);}}"
view :by_createdBy
end
end
But when I access by_documentType it's returning nil
Android.find_by_documentType('Survey')

Thanks Friends!
Finally I found the Answer, I changed my Model as follows
require 'couchrest_model'
class Android < CouchRest::Model::Base
property :description, String
property :_id, String
property :_rev, String
property :documentType, String
property :surveyId, String
design do
view :by_document_type,:map =>"function(doc) {if (doc.documentType == \"Survey\") {emit([doc._id,doc.title], 1);}}",:reduce=>"function(keys, values, rereduce) {return sum(values);}"
view :by_surveyId,:map =>"function(doc) {emit([doc.surveyId], 1);}",:reduce=>"function(keys, values, rereduce) {return sum(values);}"
end
end
And now able to call this view as required. following returns all the documents which has document type 'Survey'
Android.by_document_type.rows
And Based on Survey ID selection, I can retrieve all documents which belongs to selected survey id, as follows
Android.by_surveyId.key('Selected Survey ID goes here').rows

Try Android.by_documentType.key('Survey')

Related

Access Nested Netsuite Ruby Hash

I am trying to access a Netsuite Ruby Hash (Netsuite gem) and return orders which need updating from the db, the process uses two service objects, one to get the orders from db, (ListOrdersService), and the this file to compare those against modified ones in Netsuite. Is all working except I am having problems getting some of the nested values in Netsuite in to the output. Code is below with a troublesome item commented out. Its just an each method which compares dates then puts the needed orders in returned value.
def process_order_updates
get_order_updates = []
# Get all our open orders from DB
bj_open_orders = ListOrdersService.new.call
# Get all identical open orders from Netsuite
bj_open_orders.each do |item|
netsuite_sales_orders = NetSuite::Records::SalesOrder.get(item['sales_order_internal_id'])
# Compare the last modified date from Netsuite to the last checked date from app DB
if netsuite_sales_orders.present? && netsuite_sales_orders.last_modified_date > item['last_checked_date']
# If the last modified date is newer, then we create a new hash with the updated order info
get_order_updates << {
sales_order_internal_id: item['sales_order_internal_id'],
order_status: item['order_status']
# quantity_fulfilled: item['items_list']['item']['quantity_fulfilled']
}
puts "still open order #{item['sales_order_internal_id']} needs to be updated, it was last checked by at #{item['last_checked_date']} but it was just modified, on #{netsuite_sales_orders.last_modified_date}"
end
end
puts "Here are the orders that need to be updated: #{get_order_updates}"
end
The Netsuite file code I am referencing is below, and trying to get quantity_fulfilled, quantity_billed, and some others in the file. items_list is a top level item
"item_list": {
"list": [
{
"attributes": {
"item": {
"internal_id": "110",
"external_id": null,
"type": null,
"attributes": {
"name": "000002 Kerosene (UN1223) 3.PGIII (D/E)"
}
},
"expand_item_group": false,
"quantity": "1000.0",
"units": {
"internal_id": "1",
"external_id": null,
"type": null,
"attributes": {
"name": "ltr"
}
},
"description": "Kerosene (UN1223) 3.PGIII (D/E)",
"price": {
"internal_id": "-1",
"external_id": null,
"type": null,
"attributes": {}
},
"rate": "0.81",
"amount": "810.0",
"is_closed": false,
"gross_amt": "850.5",
"line": "1",
"cost_estimate_type": "_averageCost",
"cost_estimate": "900.79",
"quantity_back_ordered": "0.0",
"quantity_billed": "0.0",
"quantity_committed": "1000.0",
"quantity_fulfilled": "0.0",
"tax1_amt": "40.5",
"tax_code": {
"internal_id": "2214",
"external_id": null,
"type": null,
"attributes": {
"name": "VAT:RDR-5%"
}
},
Any tips on how to get those items, directly or with a hashmap welcome Thanks

Does TypeORM have a way to search for all documents with an array containing a value?

My goal is to use an input array of strings (fake emails) as a search query for documents in my MongoDB database, which I am powering using TypeORM. This way if I want to search for documents using more than one email at a time, I can do that. Meaning I want to be able to feed in:
query = ["kim#gmail.com", "jim#gmail.com", "sarah#gmail.com"] and get 3 different documents where document one has kim#gmail.com as the attendee, jim#gmail.com is another document's attendee field, and sarah#gmail.com is the third document's attendee (or is among them).
I want to use an email as a query to search for and return all documents where the array field has the email in the array.
So as an example here is the results for the "get all documents" endpoint right now:
[
{
"_id": "6283d7ad706445dc33319bcb",
"hostUsername": "jack",
"hostEmail": "jack#outlook.com",
"meetingName": "nervous-fish-hautily-vetting",
"startTime": "2022-12-12T08:00:00.000Z",
"attendees": [
"kate#gmail.com",
"sawyer#gmail.com"
]
},
{
"_id": "6284235e662f7dfb073e2cbc",
"hostUsername": "jacob",
"hostEmail": "jacob#gmail.com",
"meetingName": "eager-fish-hautily-vetting",
"startTime": "2022-12-12T08:00:00.000Z",
"attendees": [
"kate#gmail.com",
"benjaminlinus#gmail.com"
]
},
{
"_id": "6283d7c3706445dc33319bcc",
"hostUsername": "richard",
"hostEmail": "richard#outlook.com",
"meetingName": "eager-cat-hautily-subtracting",
"startTime": "2022-12-12T08:00:00.000Z",
"attendees": [
"johnlocke#gmail.com",
"hurley#gmail.com"
]
},
{
"_id": "6283d82b706445dc33319bcd",
"hostUsername": null,
"hostEmail": "richard#outlook.com",
"meetingName": "nervous-cat-hautily-jumping",
"startTime": "1970-01-01T00:00:00.000Z",
"attendees": null
},
{
"_id": "6283d8af706445dc33319bce",
"hostUsername": null,
"hostEmail": "richard#outlook.com",
"meetingName": "eager-plant-ignorantly-jumping",
"startTime": "1970-01-01T00:00:00.000Z",
"attendees": null
}
]
I want to query the database with ["kate#gmail.com"] and get back the two results that have "kate#gmail.com" in the attendees field.
The closest solution (that doesn't work) is the one I found in this GitHub issue and also another close solution (that doesn't work) in this StackOverflow question
Here is me implementing those two suggestions:
import { In } from "typeorm";
async searchMeetingsByDetails(
attendees?: string[]
): Promise<IMeeting[]> {
console.log(attendees, 39);
const meetingsByAttendees = attendees
? await this.meetingRepository.find({
where: {
attendees: In([...attendees]),
},
})
: [];
return [
meetingsByAttendees,
].flat();
}
This gives me an empty array [] when the input is ["kate#gmail.com"] so if the In() thing worked, it would give results.
const meetings = await this.meetingRepository
.createQueryBuilder("meeting")
.where("meeting.attendees IN (:attendees)", {
attendees: [...attendees],
});
This one gives ERROR [ExceptionsHandler] Query Builder is not supported by MongoDB. TypeORMError: Query Builder is not supported by MongoDB.

How to create dynamic node relation in neo4j for dynamic data?

I was able to create author nodes directly from the json file . But the challenge is on what basis or how we have to link the data. Linking "Author" to "organization". since the data is dynamic we cannot generalize it. I have tried with using csv file but, it fails the conditions when dynamic data is coming. For example one json record contain 2 organization and 3 authors, next record will be different. Different json record have different author and organization to link. organization/1 represent organization1 and organization/2 represents organization 2. Any help or hint will be great. Thank you. Please find the json file below.
"Author": [
{
"seq": "3",
"type": "abc",
"identifier": [
{
"idtype:auid": "10000000"
}
],
"familyName": "xyz",
"indexedName": "MI",
"givenName": "T",
"preferredName": {
"familyName": "xyz1",
"givenName": "a",
"initials": "T.",
"indexedName": "bT."
},
"emailAddressList": [],
"degrees": [],
"#id": "https:abc/2009127993/author/person/3",
"hasAffiliation": [
"https:abc/author/organization/1"
],
"organization": [
[
{
"identifier": [
{
"#type": "idtype:uuid",
"#subtype": "idsubtype:affiliationInstanceId",
"#value": "aff2"
},
{
"#type": "idtype:OrgDB",
"#subtype": "idsubtype:afid",
"#value": "12345"
},
{
"#type": "idtype:OrgDB",
"#subtype": "idsubtype:dptid"
}
],
"organizations": [],
"addressParts": [],
"sourceText": "",
"text": " Medical University School of Medicine",
"#id": "https:abc/author/organization/1"
}
],
[
{
"identifier": [
{
"#type": "idtype:uuid",
"#subtype": "idsubtype:affiliationInstanceId",
"#value": "aff1"
},
{
"#type": "idtype:OrgDB",
"#subtype": "idsubtype:afid",
"#value": "7890"
},
{
"#type": "idtype:OrgDB",
"#subtype": "idsubtype:dptid"
}
],
"organizations": [],
"addressParts": [],
"sourceText": "",
"text": "K University",
"#id": "https:efg/author/organization/2"
}
]
Hi I see that Organisation is part of the Author data, so you have to model it like wise. So for instance (Author)-[:AFFILIATED_WITH]->(Organisation)
When you use apoc.load.json which supports a stream of author objects you can load the data.
I did some checks on your JSON structure with this cypher query:
call apoc.load.json("file:///Users/keesv/work/check.json") yield value
unwind value as record
WITH record.Author as author
WITH author.identifier[0].`idtype:auid` as authorId,author, author.organization[0] as organizations
return authorId, author, organizations
To get this working you will need to create include apoc in the plugins directory, and add the following two lines in the apoc.conf file (create one if it is not there) in the 'conf' directory.
apoc.import.file.enabled=true
apoc.import.file.use_neo4j_config=false
I also see a nested array for the organisations in the output why is that and what is the meaning of that?
And finally I see also in the JSON that an organisation can have a reference to other organisations.
explanation
In my query I use UNWIND to unwind the base Author array. This means you get for every author a 'record' to work with.
With a MERGE or CREATE statement you can now create an Author Node with the correct properties. With the FOREACH construct you can walk over all the Organization entry and create/merge an Organization node and create the relation between the Author and the Organization.
here an 'psuedo' example
call apoc.load.json("file:///Users/keesv/work/check.json") yield value
unwind value as record
WITH record.Author as author
WITH author.identifier[0].`idtype:auid` as authorId,author, author.organization[0] as organizations
// creating the Author node
MERGE (a:Author { id: authorId })
SET a.familyName = author.familyName
...
// walk over the organizations
// determine
FOREACH (org in organizations |
MERGE (o:Organization { id: ... })
SET o.name = org.text
...
MERGE (a)-[:AFFILIATED_WITH]->(o)
// if needed you can also do a nested FOREACH here to process the Org Org relationship
)
Here is the JSON file I used I had to change something at the start and the end
[
{
"Author":{
"seq":"3",
"type":"abc",
"identifier":[
{
"idtype:auid":"10000000"
}
],
"familyName":"xyz",
"indexedName":"MI",
"givenName":"T",
"preferredName":{
"familyName":"xyz1",
"givenName":"a",
"initials":"T.",
"indexedName":"bT."
},
"emailAddressList":[
],
"degrees":[
],
"#id":"https:abc/2009127993/author/person/3",
"hasAffiliation":[
"https:abc/author/organization/1"
],
"organization":[
[
{
"identifier":[
{
"#type":"idtype:uuid",
"#subtype":"idsubtype:affiliationInstanceId",
"#value":"aff2"
},
{
"#type":"idtype:OrgDB",
"#subtype":"idsubtype:afid",
"#value":"12345"
},
{
"#type":"idtype:OrgDB",
"#subtype":"idsubtype:dptid"
}
],
"organizations":[
],
"addressParts":[
],
"sourceText":"",
"text":" Medical University School of Medicine",
"#id":"https:abc/author/organization/1"
}
],
[
{
"identifier":[
{
"#type":"idtype:uuid",
"#subtype":"idsubtype:affiliationInstanceId",
"#value":"aff1"
},
{
"#type":"idtype:OrgDB",
"#subtype":"idsubtype:afid",
"#value":"7890"
},
{
"#type":"idtype:OrgDB",
"#subtype":"idsubtype:dptid"
}
],
"organizations":[
],
"addressParts":[
],
"sourceText":"",
"text":"K University",
"#id":"https:efg/author/organization/2"
}
]
]
}
}
]
IMPORTANT create unique constraints for Author.id and Organization.id!!
In this way you can process any json file with an unknown number of author elements and an unknown number of affiliated organisations

Renaming type for FSharp.Data JsonProvider

I have a JSON that looks something like this:
{
...
"names": [
{
"value": "Name",
"language": "en"
}
],
"descriptions": [
{
"value": "Sample description",
"language" "en"
}
],
...
}
When using JsonProvider from the FSharp.Data library, it maps both fields as the same type MyJsonProvider.Name. This is a little confusing when working with the code. Is there any way how to rename the type to MyJsonProvider.NameOrDescription? I have read that this is possible for the CsvProvider, but typing
JsonProvider<"./Resources/sample.json", Schema="Name->NameOrDescription">
results in an error.
Also, is it possible to define that the Description field is actually an Option<MyJsonProvider.NameOrDescription>? Or do I just have to define the JSON twice, once with all possible values and the second time just with mandatory values?
[
{
...
"names": [
{
"value": "Name",
"language": "en"
}
],
"descriptions": [
{
"value": "Sample description",
"language" "en"
}
],
...
},
{
...
"names": [
{
"value": "Name",
"language": "en"
}
],
...
}
]
To answer your first question, I do not think there is a way of specifying such renaming. It would be quite reasonable option, but the JSON provider could also be more clever when generating names here (it knows that the type can represent Name or Description, so it could generate a name with Or based on those).
As a hack, you could add an unusued field with the right name:
type A = JsonProvider<"""{
"do not use": { "value_with_langauge": {"value":"A", "language":"A"} },
"names": [ {"value":"A", "language":"A"} ],
"descriptions": [ {"value":"A", "language":"A"} ]
}""">
To answer your second question - your names and descriptions fields are already arrays, i.e. ValueWithLanguge[]. For this, you do not need an optional value. If they are not present, the provider will simply give you an empty array.

Output JSON array without the class name in every array element

The default way to output JSON in rails is some thing like:
Code:
render :json => friends.to_json(:only => [:username, :avatar_file_name, :id ])
Output
{"friends" :
[{"user":
{"avatar_file_name": "image1.jpg", "username": "user1", "id": 1}},
{"user":
{"avatar_file_name": "image2.jpg", "username": "user2", "id": 2}},
{"user":
{"avatar_file_name": "image3.jpg", "username": "user3", "id": 3}}
]}
But i want something like:
{"friends" :
{"user": [
{"avatar_file_name": "image1.jpg", "username": "user1", "id": 1},
{"avatar_file_name": "image2.jpg", "username": "user2", "id": 2},
{"avatar_file_name": "image3.jpg", "username": "user3", "id": 3}
]}
}
The class is specified by the array name.
Last.fm also uses this syntax see Last.fm 'API-user.getfriends'
The solution to this problem is commenting the line
ActiveRecord::Base.include_root_in_json = true
in initializers/new_rails_defaults.rb
Or setting ActiveRecord::Base.include_root_in_json to false.
You can use javascript to reformat it:
var json =
{
"friends" :
{ "user": [] }
}
var i = 0;
for ( x in friends )
{
json.friends.user[i].avatar_file_name = x.user.avatar_file_name; // add more fields.
i++;
}
Something among those lines.
JSON is normally used to represent objects in a text format.
So if you like the secon output you must change your objects.
The first output says:
there is a friends object which is a array of user, each user has some properties among which you chose to expose username, avatar_file_name, id
The second output says:
there is a friends object which contains a user object which is an array of unnamed objects, each unnamed objects has some properties...
This second output is not writable in JSON syntax.
It might be:
{"friends" :
{"user": [
["avatar_file_name", "username", "id"],
["image1.jpg", "user1", 1],
["image2.jpg", "user2", 2],
["image3.jpg", "user3", 3]
]}
}
This says:
there is a friends object which contains a user object which is an array of array (a table with field names on first row) ...

Resources