How to add resource and specify related element? - rest

I have a simple API for a game tip website:
/class is the endpoint for in game classes
/tip is the endpoints for the tips
/user is the endpoint for the users
Each tip has 3 relations:
(:User)-[:AUTHORED]-(:Tip)
(:Class)<-[:FOR]-(:Tip)
(:Class)<-[:AGAINST]-(:Tip)
When I create a Tip using POST, I do'nt know how to add relations at the create time.
I can do this way: Add relation to another node in SDN4 + REST after creating the resource, but I want to do it with only one query.
EDIT:
I tried to POST this:
'{"content":"TEST", "forClass":"/class/2", "againstClass":"/class/2"}'
and the item has been created, no InvalidArgument Exception raised, but if I go to my class resource's tips, I don't have any tips:
GET /class/2/tips:
{
"_embedded" : {
"tip" : [ ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/class/2/tips"
}
}
}
GET /tip/9 (the created one):
{
"content" : "TEST",
"_links" : {
"self" : {
"href" : "http://localhost:8080/tip/9"
},
"tip" : {
"href" : "http://localhost:8080/tip/9"
},
"author" : {
"href" : "http://localhost:8080/tip/9/author"
},
"againstClass" : {
"href" : "http://localhost:8080/tip/9/againstClass"
},
"forClass" : {
"href" : "http://localhost:8080/tip/9/forClass"
}
}
}
GET /tip/9/forClass:
{
"name" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/class/2"
},
"bnSClass" : {
"href" : "http://localhost:8080/class/2"
},
"tips" : {
"href" : "http://localhost:8080/class/2/tips"
}
}
}

Related

Missing rollover_alias index setting in OpenSearch

I am trying to setup index rollover in OpenSearch with simple min_doc_count condition, but I am getting "message": "Missing rollover_alias index setting [index=app_logs-000002]" error.
I have a rollover alias called app_logs, and also have the following policy (for demo purpose it is dummy to rollover after 3 documents) attached to indexes:
PUT _plugins/_ism/policies/rollover_policy
{
"policy": {
"description": "Rollover policy",
"default_state": "rollover",
"states": [
{
"name": "rollover",
"actions": [
{
"rollover": {
"min_doc_count": 3
}
}
],
"transitions": []
}
],
"ism_template": [
{
"index_patterns": [
"app_logs-*"
]
}
]
}
}
GET _cat/aliases:
app_logs app_logs-000001 - - - false
app_logs app_logs-000002 - - - true
GET _cat/indices:
yellow open app_logs-000002 V4j0gxaYTcqoQZvtd0u2zc 1 1 6 0 4.1kb 4.1kb
yellow open app_logs-000001 AnPjlOq6Q5We411z2q_YpQ 1 1 5 0 18.8kb 18.8kb
...
When doing
GET _opendistro/_ism/explain/app_logs-000002?pretty I get:
{
"app_logs-000002" : {
"index.plugins.index_state_management.policy_id" : "rollover_policy",
"index.opendistro.index_state_management.policy_id" : "rollover_policy",
"index" : "app_logs-000002",
"index_uuid" : "V4j0gxaYTcqoQZvtd0u2zc",
"policy_id" : "rollover_policy",
"policy_seq_no" : -2,
"policy_primary_term" : 0,
"rolled_over" : false,
"index_creation_date" : 1659299029428,
"state" : {
"name" : "rollover",
"start_time" : 1659299410303
},
"action" : {
"name" : "rollover",
"start_time" : 1659424192817,
"index" : 0,
"failed" : true,
"consumed_retries" : 3,
"last_retry_time" : 1659424804833
},
"step" : {
"name" : "attempt_rollover",
"start_time" : 1659424192817,
"step_status" : "failed"
},
"retry_info" : {
"failed" : false,
"consumed_retries" : 0
},
"info" : {
"message" : "Missing rollover_alias index setting [index=app_logs-000002]"
},
"enabled" : false
},
"total_managed_indices" : 1
}
When I do GET app_logs-000002/_settings I get:
{
"app_logs-000002" : {
"settings" : {
"index" : {
"creation_date" : "1659299029428",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "V4j0gxaYTcqoQZvtd0u2zc",
"version" : {
"created" : "136227827"
},
"provided_name" : "app_logs-000002"
}
}
}
}
so yes rollover alias setting is really missing there. But I would expect that this will be added automatically.
When I do GET _template I get:
{
"ism_rollover" : {
"order" : 0,
"index_patterns" : [
"app_logs-*"
],
"settings" : {
"index" : {
"opendistro" : {
"index_state_management" : {
"rollover_alias" : "app_logs"
}
}
}
},
"mappings" : { },
"aliases" : { }
}
}
so rollover_alias is there in template. Why this is not used in a new index from template?
Thanks!
I experienced a similar problem. The issue was that the indices needed to be created after the ism policy and template. I'm not sure if you managed to find a solution but perhaps for those future users this could prove useful.
Some docs:
Very useful sample on setting up a rolling index strategy: https://opensearch.org/docs/latest/im-plugin/ism/policies/#sample-policy-with-ism-template-for-auto-rollover
Official AWS docs on the same topic with some examples: https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ism.html.
A great writeup on common errors experienced when implementing a rolling index ISM policy: https://aws.amazon.com/premiumsupport/knowledge-center/opensearch-failed-rollover-index/
In your case it appears that the policy was not correctly applying to your indices which is likely a result of you creating your indices before the policy and template were created. If you want to add a policy to an index see the step 6 of Create an ISM policy in the linked AWS docs above:
POST _plugins/_ism/add/my-index
{
"policy_id": "my-policy-id"
}
Here is how I went about solving this problem using a policy and template:
Implement an ISM policy (as you did above)
Create an ISM template
PUT _template/ism_rollover_app
{
"index_patterns": "app_logs-*",
"settings": {
"index": {
"opendistro.index_state_management.rollover_alias": "app_logs"
}
}
}
Create an initial index called app_logs-00001 (or some variant that matches the regex ^.*-\d+$)
This should hopefully see app_logs-00001 be created from the ism_rollover_app template and have the app_logs index associated with it. This should subsequently fix this missing alias issue.

How to get the total number of times each object has been referenced in a collection?

So what i am trying to find is how many time each kite was flown by each person, the db looks like this:
{
"_id" : ObjectId("5bccf4d7ac8fa95f43a964c2"),
"KITE" : {
"registration" : "DTH498"
}
}
{
"_id" : ObjectId("5bccf4d7ac8fa95f43a964c3"),
"KITE" : {
"registration" : "HKJ607"
}
}
{
"_id" : ObjectId("5bccf4d7ac8fa95f43a964c4"),
"KITE" : {
"registration" : "GCF21"
}
}
{
"_id" : ObjectId("5bccf4d7ac8fa95f43a964cf"),
"PERSON" : {
"name" : "H.Y",
"used" : [
{
"registration" : "DTH498"
},
{
"registration" : "HKJ607"
},
{
"registration" : "GCF21"
}
]
}
}
{
"_id" : ObjectId("5bccf4d7ac8fa95f43a9leo5"),
"PERSON" : {
"name" : "T.G",
"used" : [
{
"registration" : "DTH498"
},
{
"registration" : "HKJ607"
},
{
"registration" : "GCF21"
}
]
}
}
{
"_id" : ObjectId("5bccf4d7ac8fro4943a01pak"),
"PERSON" : {
"name" : "X.L",
"used" : [
{
"registration" : "DTH498"
},
{
"registration" : "HKJ607"
},
{
"registration" : "GCF21"
}
]
}
}
Right now i can only use the aggregation framework, with that said i've managed to list all kites that have been used:
db.data.aggregate([
{"$unwind":"$PERSON.used"},
{"$group":{"_id":"$PERSON.used.registration"}}
]).pretty();
The result i'm trying to get to would have the registration of the kite and the number of times it has been used overall.
I'm not sure how it would look but, what im thinking is:
1. Somehow get all used array objects registrations into a new array so it one big list of all the times each kite has been used
2. Group the array by registration and use sum to display how many duplicates each group had.
I DID IT, WOOOO!
so if anyone ever stumbles upon my question, heres the answer.
First unwind the used array
Second project only the registrations
Third group with an _id of registration and count with $sum
db.data.aggregate([
{"$unwind":"$PERSON.used"},
{"$project":{"registration":"$PERSON.used.registration","_id":0}},
{"$group":{"_id":"$registration", "count":{"$sum":1}}}
]);

Mongodb update and delete operations in a single query

I have documents in which I would like to update the hostUser with one of the members of the document,also have to delete the record from the member document and add the chips of the deleted member in the club chips.
Here is the sample document.
{
"_id" : "1002",
"hostUser" : "1111111111",
"clubChips" : 10000,
"requests" : {},
"profile" : {
"clubname" : "AAAAA",
"image" : "0"
},
"tables" : [
"SJCA3S0Wm"
],
"isDeleted" : false,
"members" : {
"1111111111" : {
"chips" : 0,
"id" : "1111111111"
},
"2222222222" : {
"chips" : 0,
"id" : "2222222222"
}
}
}
This is what I have tried.
db.getCollection('test').updateMany({"hostUser":"1111111111"},
{"$set":{"hostUser":"2222222222"},"$unset":{"members.1111111111":""}})
This is how you would handle unset and set in a single call to updateMany. Can you please clarify what you meant by "check if the values exist in the member field"?
db.getCollection('test').updateMany(
{"hostUser":"1111111111"},
{
'$set': {"hostUser":"2222222222"} ,
'$unset': {"members.1111111111":""}
}
)

Python check MongoDB field exists or not

I have two collections one is websites which stores information like:
{
"_id" : ObjectId("5ac5efd6a37efa4c0e28f5aa"),
"main_id" : 3,
"status" : "",
"website" : "http://test.com",
"last_access_time" : "2018-04-16 17:49:03",
"links" : [
{
"link_id" : "test-1",
"link" : "test1.html"
},
{
"link_id" : "test-2",
"link" : "test.html"
}
]
}
And another is website_info in which I want store info like:
{
"_id" : ObjectId("5ad72ddecf45b60dffcbf9f2"),
"main_id" : 3,
"last_access_time" : "2018-04-18 15:37:02",
"test-1" : {
"no_of_links" : 55,
"links_2" : [
{
"link" : "/home",
"link_id" : "secnd-1",
},
{
"link" : "/login",
"link_id" : "secnd-2",
},
{
"link" : "/services",
"link_id" : "secnd-3",
}
]
},
"test-2" : {
"no_of_links" : 55,
"links_2" : [
{
"link" : "/home",
"link_id" : "secnd-1",
},
{
"link" : "/login",
"link_id" : "secnd-2",
},
{
"link" : "/services",
"link_id" : "secnd-3",
}
]
}
}
I am using Python3 and mongoDB.
Here I want to check the field like "link_id" which is "test-1" in the website_info for main_id = 3 exists or not. If it is exists I will update for same, if does not exists I want to insert new record set.
The thing is how to check whether field "test-1" (which is the value from websites collection) in website_info collection exists or not.
Help is appreciated.
Here in my case, link_id will be unique in website_info collection. So no need to check for main_id, only checking for link_id solved my issue, like:
#classmethod
def find_link(self, link_id):
cursor = self.db.collection.find({link_id: {'$exists': True}} )
results = list(cursor)
return results
And check for exists like:
if(len(is_exists)>0):
#do if exists

MongoDB aggregation to return nested groups with values as keys?

My documents look like this:
{
"_id" : "Tvq579754r",
"Status" : "passed",
"Title" : "up08c",
"ProjectID" : "Tvq5p",
"Version" : "1.0.0",
"Platform" : "platform_x",
"METRIC_A" : 11114.85,
"METRIC_B" : 68.9,
"METRIC_C" : 65.35,
},
{
"_id" : "Tvq579755r",
"Status" : "passed",
"Title" : "up09c",
"ProjectID" : "Tvq5p",
"Version" : "1.0.0",
"Platform" : "platform_x",
"METRIC_A" : 21114.85,
"METRIC_B" : 168.9,
"METRIC_C" : 165.35,
},
{
"_id" : "Tvq579756r",
"Status" : "passed",
"Title" : "up09c",
"ProjectID" : "Tvq5p",
"Version" : "1.0.0",
"Platform" : "platform_x",
"METRIC_A" : 31114.85,
"METRIC_B" : 268.9,
"METRIC_C" : 265.35,
}
Now I have no problem grouping and getting $avg and $sum of my METRIC_ fields by grouping by ProjectID, Version, Platform and Title, but what I'd like to do within the aggregation framework (if possible) is to return an object that uses the grouped values as keys, such as:
{
<Project ID> : {
<Version> : {
<Platform> : {
<Title> : {
"METRIC_A": <sum of METRIC_A>,
"METRIC_B": <sum of METRIC_B>,
"METRIC_C": <sum of METRIC_C>,
}
}
}
}
}
Or, in context of my example:
{
'Tvq5p' : {
'1.0.0' : {
'platform_x' : {
'up08c' : {
"METRIC_A": 11114.85,
"METRIC_B": 68.9,
"METRIC_C": 65.35,
},
'up09c' : {
"METRIC_A": 52229.7,
"METRIC_B": 437.8,
"METRIC_C": 430.7,
}
}
}
}
}
I am currently doing it once the query results are received by the consuming service, which isn't terribly slow or anything, but I just thought it would be nice to come that way right out of Mongo. Is this even possible?
Thanks.
In MongoDB there is the group operation.
db.records.group( {
key: { 'platform_x': 1, 'title': 1 },
reduce: function(cur, result) {
result.metric_a += cur.metric_a;
result.metric_b += cur.metric_b;
result.metric_c += cur.metric_c;
},
initial: { metric_a = 0, metric_b = 0, metric_c = 0 }
} )
If that doesn't work I'd recommend a Map Reduce.