Friday, August 24, 2018

How to store comments in NoSQL (MongoDB)?

1 way

Comments are embedded in Post document:

{
  "_id": ObjectId(12345),
  "title": "Cat ate elephant!",
  "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean convallis pretium vulputate.",
  "comments": [
    {"name": "Cat", "body": "MEOW!"},
    {"name": "Elephant", "body": "I was eaten by cat, lol!"},
    {"name": "Human", "body": "I am hungry!"}
  ]
}

2 way

Relationship between Post and Comments (in separate documents). Post has many Comments:

// POST //
{
  "_id": ObjectId(12345),
  "title": "Cat ate elephant!"
  "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean convallis pretium vulputate."
}


// Comments //

{
  "_id": ObjectId(...),
  "post_id": ObjectId(12345),
  "name": "Cat",
  "body": "MEOW!"
}

{
  "_id": ObjectId(...),
  "post_id": ObjectId(12345),
  "name": "Elephant",
  "body": "I was eaten by cat, lol!"
}

{
  "_id": ObjectId(...),
  "post_id": ObjectId(12345),
  "name": "Human",
  "body": "I am hungry!"
}

Which way is better?

Solved

Method 1

  • No need to joins => fast access to data
  • The NoSQL way of doing it
  • Every comment is just related to just that post, so why not store them together(you store the title and the body together ;)

If you have large documents, >15.5 Megabyte, and you gets a loot of comments then you probably will need to store them somewhere else. This because the maximum document size is 16 Megabyte.

Method 2 is the RDMBS way of doing it, Mongo does not have joins inbuilt so you will need to do them in your application.


Because no comment belongs to more than one post, it makes more sense to embed them in the Post document in NoSQL. So when you retrieve your Post you immediately have your comments as well, in 1 query.


The first way is preferred, as long as the document is not write-heavy. If you're going to have 5000 comments added to a post within a minute, then use the second method.


Monday, August 20, 2018

Same prefix, multiple namespace in XML - How to add element attrib without affecting other in Python

I have the below input XML:



    
        
            
            
            
        
    


As you can see, xmlns is used for two namespaces , "urn:jboss:domain:4.1" and "urn:jboss:domain:jmx:1.3"

I would like to add an attribute to host element

Below is my code in Python:

from xml.etree import ElementTree as ET

def parse_xml():
    ET.register_namespace('','urn:jboss:domain:4.1')
    tree = ET.parse('sample.xml')
    root = tree.getroot()
        for elements in tree.iter():
        if "host" in elements.tag :
            elements.attrib['name'] = "slaveOne"
            print elements.attrib
            tree.write('sample.xml')

The above code changes the XML as below:



    
        
            
            
            
        
    


tree.write('sample.xml')

Changes all elements belonging to same prefix in this case

ET.register_namespace('','urn:jboss:domain:4.1')

  • How do i isolate the changes only to host element

Solved

You can try using minidom:

from xml.dom import minidom

doc = minidom.parse("sample.xml")

#getElementsByTagName returns NodeList
#grab first
host = doc.getElementsByTagName("host")[0]

#set attr -> value
#look at setAttributeNS in minidom docs for namespaces 
host.setAttribute('name', '123')

#write to file
with open('sample2.xml', 'w') as xmlfile:
    doc.writexml(xmlfile)

Take a look at xml.sax package and this XML Processing Modules page too.


Sunday, August 19, 2018

What is really necessary for importing MongoDB in Gradle/Intellij?

I'm building a java application with Intellij-idea, Gradle and Mongo. I created a new Gradle project and I was having some trouble importing mongodb-java-driver inside my project. I modified this piece of code inside build.gradle:

dependencies {
 testCompile group: 'junit', name: 'junit', version: '4.11'
 compile 'org.mongodb:mongo-java-driver:3.4.1'
}

But was unable to use Mongo with Java. My External Libraries didn't have any Mongo jar. Then I saw here that I should add the application plugin to my build.gradle. I searched on the official docs that this plugin "will automatically add run task that will execute the specified main class with all the runtime dependencies automatically put on the classpath:" as the answer linked above stated. But this didn't solved my problem.

Then I added the idea plugin, since I saw here that "The IDEA plugin generates files that are used by IntelliJ IDEA, thus making it possible to open the project from IDEA". I didn't think that would help me but was worth a try. Unfortunately, this didn't helped either.

After this I saw here that I should synchronize my project. Since I created this from zero and didn't import any complete project from outside I didn't understand why I should synchronize it. While it was synchronized, I saw Intellij was downloading mongo-java-driver. After that, I still was unable to use Mongo. I had to add the downloaded jar to my project class path, as this was one of the suggested corrections given by Intellij.

I've come from Eclipse/Maven and I'm discovering how Intellij/Gradle behave. So my question is what is strictly necessary to use mongodb-java-driver on Intellij/Gradle and why I had to synchronize my project? Is this the correct way of using Gradle? Always building and synchronizing after?

Saturday, August 18, 2018

How to draw path like canvas in Android using OpenGL ES 2?

I have tried Canvas in Android, and I can make sketch or path by moving my finger on the screen. Now, I want to do the same thing using OpenGL 2. I'm new to OpenGL programming but I have tried several method to draw a Line using GLES20.glDrawArray(...) and a Line Shape class but still, this just make a straight line not like a free-form path i wanted just like when I use canvas. and also, if i try to draw per line segment each time ACTION_MOVE, concurrent modification exception often happens since i store each Line segment in an ArrayList. is there any helping API by OpenGL to achieve this? if there's or there isn't, how can i make this? Thanks!

Solved

If you want to draw a consistent line along a path, then you're in fact trying to draw many short lines which are all connected to each other.

I think the most intuitive way of doing this, is adding each point on the path into an array of points, and then, maintaining a float buffer, where each 3 items describe a single point on the path (x,y,z). Then, for every point which is added to this vertex buffer, you should add two integers into an index buffer. If you're new to index buffers, the way it works (when you're working with lines), is it tells OpenGL which two vertexes are connected. For instance:

Say you have 3 points. Inside the Vertex buffer, you would have 9 floats - 3 points * 3 coordinates for each point. We would like the 1st point to be connected to the 2nd, and the 2nd point to be connected to the 3rd. We can do this by using an Index Buffer. In the index buffer, we will place 2 integers for every vertex connection. For connecting the 1st point to the 2nd, we will player 0 & 1 into the buffer. This says that the 1st 3 coordinates in the vertex buffer are connected to the 2nd 3 coordinates in the vertex buffer. Then, we will place 1 & 2 in the index buffer. This says that the 2nd 3 coordinates in the vertex buffer are connected to the 3rd 3 coordinates in the vertex buffer - and so on.

Vertex Buffer:
{
  0, 0, 0, // Index 0
  1, 1, 1, // Index 1
  2, 3, 4  // Index 2
}

Index Buffer:
{
  0, 1, // Connect Index 0 to Index 1
  1, 2  // Connect Index 1 to Index 2
}

You will need to call glDrawElements rather than glDrawArrays, but the idea is the same - you only need to maintain an additional buffer for the indexes, and make sure to always update both buffers each time you add a new point.

As for the concurrent modification exception - you need to be a bit careful here. If you add a point to the array while you're iterating over the array (for example, with a "for each" style loop), then this will happen. A good solution is to surround any interaction with the point array with a synchronize block, and use the array itself as a mutex:

Adding:
synchronized(myPointArray)
{
  myPointArray.add(newPoint);
}


Iterating:
synchronized(myPointArray)
{
  for (PointF point : myPointArray)
  {
    // do stuff with the point
  }
}

This should get you started.