关于MongoDB节点路径搜索的几点思考

来源:互联网 发布:qt支持c语言吗 编辑:程序博客网 时间:2024/05/23 18:57

因为项目原因,需要对现有的200G的数据上进行时间秒级的测试,其中一个就是两个节点之间的路径搜索,按照之前测试思路,很自然想到树的深度搜索算法,用Java递归实现,部分代码如下:

public static void main(String[] args) throws SQLException {
        ArrayList<ArrayList<String>> list = new ArrayList<>();//储存不同的路径节点信息
        ArrayList<String> item = new ArrayList<>();//储存的是每个路径的信息,多个路径信息都存在list中
        
        try {

        
            MongoClient client = new MongoClient("192.168.1.111", 27016);
            MongoDatabase db = client.getDatabase("wq");

            col = db.getCollection("ljgx");
            // System.out.println("wnjd connect .");
            col1 = db.getCollection("ljgx");
            System.out.println("ljgx connect .");
            start = System.currentTimeMillis();

            start = System.currentTimeMillis();
            System.out.println(start);
            finding1(jd1, list, item);
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static ArrayList<ArrayList<String>> finding1(String jd, ArrayList<ArrayList<String>> list, ArrayList<String> item) {
        item.add(jd);
        
        BasicDBObject query1 = new BasicDBObject();        
        query1.put("网内节点1编号", jd);        
        FindIterable<Document> findIterable = col.find(query1);
        MongoCursor<Document> mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            // start1 = System.currentTimeMillis();
            Document d = mongoCursor.next();
            String a = d.get("网内节点2编号").toString();            
            
            if (a.equals(jd2)) {
                item.add(d.get("网内节点2编号").toString());
                list.add(item);
                item.clear();
            }
            item.add(d.get("网内节点2编号").toString());
            finding1(d.get("网内节点2编号").toString(),list,item);
           
        }
        return list;
    }


以上代码可以在数据量小的情况下正常执行,并且找到两个节点间的路径,但是200G的数据量下就会报一下错误,实际项目要求是6T


溢出错误,所以只有将递归实现改为了非递归实现

在这又遇到一个问题,对于树的深度搜索遍历的非递归实现不是很清楚,一开始写的代码如下:

public static void deepOrder(String jd) {
        ArrayDeque<Node> s = new ArrayDeque<>();
        ArrayList<Node> list = new ArrayList<>();
        int level = 0;
        Node n = new Node(jd, level);
        
        s.push(n);
        while (!s.isEmpty()) {
            String now = s.pop();// 出栈,此时第一次出栈后栈为空
           
            list.add(now);
            if (jd.equals(jd2)) {                
                for (int i = 0; i < list.size(); i++) {
                    System.out.print(list.get(i).jd + " ");                    
                }
                System.out.println();
            }            
            else {
                BasicDBObject query1 = new BasicDBObject();
                query1.put("网内节点1编号", jd);
                FindIterable<Document> findIterable = col.find(query1);
                MongoCursor<Document> mongoCursor = findIterable.iterator();
                
                while (mongoCursor.hasNext()) {
                    Document d = mongoCursor.next();
                    String a = d.get("网内节点2编号").toString();
                    s.push(a);
                }
            }
        }
    }

以上代码代码并不能得到想要的数据,归根于遍历后的数据不知道哪些该删除,该保留,怎么删除,对于数据组织上还有欠缺


代码的改进方法:

1、利用层级的思想来判断如何删掉数据

2、每个节点为一个Node对象,每个node对象下拥有一个childeList来保存自己的孩子节点


实现1:

代码如下:

    public static void main(String[] args) throws SQLException {

        try {

            MongoClient client = new MongoClient("192.168.1.111", 27016);
            MongoDatabase db = client.getDatabase("wq");

            col = db.getCollection("ljgx");
            System.out.println("ljgx connect .");
            start = System.currentTimeMillis();
            System.out.println(start);
            deepOrder(jd1);
            // System.out.println(list);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void deepOrder(String jd) {
        ArrayDeque<Node> s = new ArrayDeque<>();
        ArrayList<Node> list = new ArrayList<>();
        int level = 0;
        Node n = new Node(jd, level);
        
        s.push(n);
        while (!s.isEmpty()) {
            Node now = s.pop();// 出栈,此时第一次出栈后栈为空
            
            while (list.size() > 0 && list.get(list.size() - 1).level >= now.level) {
                list.remove(list.size() - 1);
            }
            list.add(now);
            if (now.jd.equals(jd2)) {                
                for (int i = 0; i < list.size(); i++) {
                    System.out.print(list.get(i).jd + " ");                    
                }
                System.out.println();
            }            
            else {
                BasicDBObject query1 = new BasicDBObject();
                level = now.level + 1;
                query1.put("网内节点1编号", now.jd);
                FindIterable<Document> findIterable = col.find(query1);
                MongoCursor<Document> mongoCursor = findIterable.iterator();
                
                while (mongoCursor.hasNext()) {
                    Document d = mongoCursor.next();
                    String a = d.get("网内节点2编号").toString();
                    n = new Node(a, level);
                    s.push(n);
                }
            }
        }
    }

}

class Node {
    String jd;
    int level;
    
    public Node(String no, int level) {
        this.jd = no;
        this.level = level;
    }
}

这个代码可以实现多叉树的深度遍历搜索算法(非递归),可以在小数据量上得到结果,大数据量上没有报错,但是时间很长,依然在运行


2、第二种方法没有实现,但是耗费的空间比第一种还多,所以就放弃实现了


原创粉丝点击