Arangodb csv数据导入及api使用、最短路径查询

一、导入csv 数据,

1、网上下载 航班数据 https://download.csdn.net/download/w690333243/12026892
2、本地安装Arangodb https://download.csdn.net/download/w690333243/12026899
3、环境变量配置 arangodb安装目录下的 bin路径
C:\Program Files\ArangoDB3 3.5.3\usr\bin
如果不配做环境变量,和jdk一样,cmd模式下要进入 C:\Program Files\ArangoDB3 3.5.3\usr\bin 目录下才可执行命令

arangoimp --file E:\arangodb\airports.csv --collection airports --create-collection true --type csv

arangoimp --file E:\arangodb\flights.csv --collection flights --create-collection true --type csv --create-collection-type edge

这里创建的是edge collection,为每一行创建一个edge,同时自动创建一个edge index方便快速查询(_from和_to组成了这样的index.).在csv中有两个特殊的列_from 和_to,它们的值为airports collection中的id,指明了从一个机场飞往另外一个机场。

注意:上面的命令直接使用了 _system数据库,如果你想导入到自定义数据库(如atest数据库), 新建数据库 atest,然后使用如下命令

arangoimp --file E:\arangodb\airports.csv --server.database atest --create-database true --collection airports --create-collection true --type csv
arangoimp --file E:\arangodb\flights.csv --server.database atest --create-database true --collection flights --create-collection true --type csv --create-collection-type edge

在这里插入图片描述
注:是cmd 窗口中导入,不是 arangodb shell 窗口导入
写于2019年12月11日

二、ArangoDB程序介绍

1、arangod
它是ArangoDB数据库的守护程序,运行后就是ArangoDB数据库服务器的守护进程。

2、arangosh
ArangoDB的Shell环境。

3、arangoimp
ArangoDB数据库导入工具

4、arangodump
ArangoDB数据库的备份工具

5、arangorestore
ArangoDB数据库的恢复工具

6、foxx-manager
一个Shell脚本,管理Foxx应用程序

7、arango-dfdb
ArangoDB的数据文件调试器

8、arangob
ArangoDB的测试和评分工具,主要用于ArangoDB的开发和测试。

三、java 操作数据库

1、pom.xml中 maven依赖

<dependency>
    <groupId>com.arangodb</groupId>
    <artifactId>arangodb-java-driver</artifactId>
    <version>6.4.1</version>
</dependency>

2、代码

import java.util.Map;

import com.arangodb.ArangoCollection;
import com.arangodb.ArangoCursor;
import com.arangodb.ArangoDB;
import com.arangodb.ArangoDBException;
import com.arangodb.ArangoDatabase;
import com.arangodb.entity.BaseDocument;
import com.arangodb.util.MapBuilder;

/**
 * @author wangqx
 *
 */
public class ArangodbTest {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		// 配置和打开连接以启动ArangoDB
		ArangoDB arangoDB = new ArangoDB.Builder().host("127.0.0.1", 8529).user("root").password("123456").build();
		try {
    
    
			// 创建数据库
			String dbName = "TestDbb";
			ArangoDatabase mydb = arangoDB.db(dbName);   获取数据库实例
			// System.out.println("mydb:"+mydb);
			if (!mydb.exists()) {
    
      如果数据库不存在
				arangoDB.createDatabase(dbName);   创建数据库
				mydb.create();//或者使用这个方法
			}

			// 创建Collection集合
			String collectionName = "TestCollection";
			ArangoCollection myArangoCollection = arangoDB.db(dbName).collection(collectionName);  获取集合实例
			if (!myArangoCollection.exists()) {
    
      如果集合不存在
				arangoDB.db(dbName).createCollection(collectionName);  创建集合
				myArangoCollection.create();//或者使用这个方法
			}	
			
			// 创建document文档
			BaseDocument myObject = new BaseDocument();
			//myObject.setKey("myKey");  设置每行数据的主键,可以不用设置;如果设置,则要保证唯一性
			myObject.addAttribute("name", "张三");
			myObject.addAttribute("age", 42);
			arangoDB.db(dbName).collection(collectionName).insertDocument(myObject);

			// 查询document文档
			BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey",
					BaseDocument.class);
			System.out.println("Key: " + myDocument.getKey());
			System.out.println("Attribute name: " + myDocument.getAttribute("name"));
			System.out.println("Attribute age: " + myDocument.getAttribute("age"));

			// 更新document文档
			myObject.addAttribute("sex", "男");
			arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject);

			// 删除document文档
			// arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey");

			String query = "FOR t IN TestCollection FILTER t.name == @name "
					+ "REMOVE t IN TestCollection LET removed = OLD RETURN removed";
			Map<String, Object> bindVars = new MapBuilder().put("name", "张三").get();
			//清除集合中 张三的 数据
			ArangoCursor<BaseDocument> cursor = arangoDB.db(dbName).query(query, bindVars, null, BaseDocument.class);
//					cursor.forEachRemaining(aDocument -> {
    
    
//						System.out.println("Removed document " + aDocument.getKey());
//					});
		} catch (ArangoDBException e) {
    
    
			e.printStackTrace();
		}
	}
}

更新于 2019年12月12日 16:39
参考
https://blog.csdn.net/u011119840/article/details/87856235 windows10下给arangodb导入csv数据文件
https://blog.csdn.net/chszs/article/details/20369433 ArangoDB数据库入门
https://blog.csdn.net/u011311291/article/details/86632594 ArangoDB教程(三)-使用java操作ArangoDB
https://blog.csdn.net/rensihui/article/details/78804706 ArangoDB入门教程(四)java操作ArangoDB数据库
https://www.cnblogs.com/minglex/p/9383849.html ArangoDB简单实例介绍 航班数据实例
https://blog.csdn.net/weixin_43363871/article/details/93460105 ArangoDB(三)——简单实例
http://www.it1352.com/OnLineTutorial/arangodb/arangodb_aql_example_queries.html ArangoDB - AQL示例查询
https://blog.csdn.net/u011311291/article/details/86628815 ArangoDB教程(二)-AQL语句使用,图使用,结合WEB界面端
https://blog.csdn.net/a499477783/article/details/79177307 ArangoDB数据导入
https://www.cnblogs.com/minglex/p/9705481.html ArangoDB数据导入
ArangoDB 的graph查询

3、如果要创建Edge类型的集合,即关系图。使用CollectionCreateOptions

// 集合
		ArangoCollection coll = db.collection("QidianBooks");
		
		if (!coll.exists()) {
    
    
			CollectionCreateOptions cco = new CollectionCreateOptions();
	        cco.type(CollectionType.EDGES);
	        db.createCollection("QidianBooks", cco);
		}

参考:https://blog.csdn.net/justlpf/article/details/89497099 neo4j数据库导入到arangodb

四、图 两顶点间的最短路径查询

public static void edgeTest() {
    
    
		// TODO Auto-generated method stub
		// 配置和打开连接以启动ArangoDB
		ArangoDB arangoDB = new ArangoDB.Builder().host("127.0.0.1", 8529).user("root").password("123456..xu").build();
		Set<BaseDocument> baseSet = new HashSet();
		List<BaseDocument> baseList = new ArrayList();
		try {
    
    
			// 创建数据库
			String dbName = "TestDbb";
			ArangoDatabase mydb = arangoDB.db(dbName);
			// System.out.println("mydb:"+mydb);
			mydb.drop();
			if (!mydb.exists()) {
    
    
				arangoDB.createDatabase(dbName);
			}

			// 创建Collection集合
			String collectionName = "User";
			ArangoCollection myArangoCollection = arangoDB.db(dbName).collection(collectionName);
			if (!myArangoCollection.exists()) {
    
    
				arangoDB.db(dbName).createCollection(collectionName);
				// myArangoCollection.create();
			}
			// 创建document文档
			for(int i=0;i<100;i++) {
    
    
				BaseDocument myObject = new BaseDocument();
				myObject.addAttribute("name", ToolUtils.getUserRandomName());
				myObject.addAttribute("age", ToolUtils.getRandomNum(18, 39));
				DocumentCreateEntity dEntity = myArangoCollection.insertDocument(myObject);
				dEntity.getId();
				baseSet.add(myObject);
				baseList.add(myObject);
				//System.out.println("myObject.getId():"+myObject.getId());
				//System.out.println("dEntity.getId():"+dEntity.getId());
			}
			/*
			BaseDocument myObject2 = new BaseDocument();
			myObject2.addAttribute("name", "李四");
			myObject2.addAttribute("age", 32);
			DocumentCreateEntity dEntity2 = myArangoCollection.insertDocument(myObject2);
			dEntity2.getId();
			baseSet.add(myObject2);
			baseList.add(myObject2);
			
			BaseDocument myObject3 = new BaseDocument();
			myObject3.addAttribute("name", "王五");
			myObject3.addAttribute("age", 34);
			DocumentCreateEntity dEntity3 = myArangoCollection.insertDocument(myObject3);
			dEntity3.getId();
			baseSet.add(myObject3);
			baseList.add(myObject3);
			
			
			BaseDocument myObject4 = new BaseDocument();
			myObject4.addAttribute("name", "李丽");
			myObject4.addAttribute("age", 22);
			DocumentCreateEntity dEntity4 = myArangoCollection.insertDocument(myObject4);
			dEntity4.getId();
			baseSet.add(myObject4);
			baseList.add(myObject4);
			
			
			BaseDocument myObject5 = new BaseDocument();
			myObject5.addAttribute("name", "张靓颖");
			myObject5.addAttribute("age", 31);
			DocumentCreateEntity dEntity5 = myArangoCollection.insertDocument(myObject5);
			dEntity5.getId();
			baseSet.add(myObject5);
			baseList.add(myObject5);
			
			
			BaseDocument myObject6 = new BaseDocument();
			myObject6.addAttribute("name", "王力宏");
			myObject6.addAttribute("age", 42);
			DocumentCreateEntity dEntity6 = myArangoCollection.insertDocument(myObject6);
			dEntity6.getId();
			baseSet.add(myObject6);
			baseList.add(myObject6);
			
			*/
			// 集合
			ArangoCollection coll = mydb.collection("RelationShip");
			
			if (!coll.exists()) {
    
    
				CollectionCreateOptions cco = new CollectionCreateOptions();
		        cco.type(CollectionType.EDGES);
		        mydb.createCollection("RelationShip", cco);
			}
			int count = 100;//baseList.size() * (baseList.size() -1)/2;
			for(int i = 0;i< count;i++) {
    
    
				int fromRandom = (int)(Math.random() * (baseList.size() - 1 ) + 1);
				BaseDocument fromBd = baseList.get(fromRandom);
				BaseEdgeDocument baseEdgeDocument = new BaseEdgeDocument();
				baseEdgeDocument.setFrom(fromBd.getId());
				
				int toRandom = (int)(Math.random() * (baseList.size() - 1 ) + 1);
				System.out.println("fromRandom:"+fromRandom+"  toRandom:"+toRandom);
				System.out.println("i========="+i);
				if(toRandom == fromRandom) {
    
    
					System.err.println("i========="+i);
					System.err.println("相等");
				}else {
    
    
					System.out.println("不相等");
				}
				while(toRandom == fromRandom) {
    
    
					System.err.println("需要循环");
					toRandom = (int)(Math.random() * (baseList.size() - 1 ) + 1);
					System.err.println("After  fromRandom:"+fromRandom+"  toRandom:"+toRandom);
				}
				System.out.println("i========="+i);
				BaseDocument toBd = baseList.get(toRandom);
				baseEdgeDocument.setTo(toBd.getId());
				System.out.println("insert fromBd.getId():"+fromBd.getId()+"  toBd.getId():"+toBd.getId());
				coll.insertDocument(baseEdgeDocument);
			}
			
			//String quer = "FOR p IN ANY SHORTEST_PATH @fromId TO @toId  RelationShip return p";
			String quer = "FOR p IN ANY SHORTEST_PATH @fromId TO @toId  RelationShip return p";//最短路径问题,ANY 表示任意方向 关键字,SHORTEST_PATH为最短路径 关键字
			
			Map<String, Object> bindVar = new MapBuilder()
					.put("fromId", baseList.get(8).getId())
					.put("toId", baseList.get(2).getId())
					.get();

			ArangoCursor<BaseDocument> curso = arangoDB.db(dbName).query(quer, bindVar, null, BaseDocument.class);
							curso.forEachRemaining(aDocumen -> {
    
    
								System.out.println("名称: " + aDocumen.getAttribute("name"));
							});

			// 查询document文档
			BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey",
					BaseDocument.class);
	

			// 更新document文档
			//myObject.addAttribute("sex", "男");
			//arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject);

			// 删除document文档
			// arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey");

			String query = "FOR t IN TestCollection FILTER t.name == @name "
					+ "REMOVE t IN TestCollection LET removed = OLD RETURN removed";
			Map<String, Object> bindVars = new MapBuilder().put("name", "张三").get();
			// 清除 张三的 数据
//			ArangoCursor<BaseDocument> cursor = arangoDB.db(dbName).query(query, bindVars, null, BaseDocument.class);
//							cursor.forEachRemaining(aDocument -> {
    
    
//								System.out.println("Removed document " + aDocument.getKey());
//							});
		} catch (ArangoDBException e) {
    
    
			e.printStackTrace();
		}
	}

https://blog.csdn.net/Missbelover/article/details/103228294 ArangoDB 中的Graph
https://blog.csdn.net/yuzongtao/article/details/76061897 ArangoDB AQL中的图形绘制遍历
https://blog.csdn.net/Missbelover/article/details/103228294 ArangoDB 中的Graph
https://cloud.tencent.com/developer/ask/199611 ArangoDB:图遍历中的顺序
https://blog.csdn.net/xugc2015/article/details/100043751 ArangoDb学习笔记————AQL tutorial(四)
https://blog.csdn.net/xugc2015/article/details/100042396 ArangoDb学习笔记————AQL tutorial(二)
https://blog.csdn.net/gxq926/article/details/90239682Arangodb最短路径查询语法
https://www.cnblogs.com/litufu/articles/9651149.html ArangoDB 学习笔记 (4)graph 航班信息方面的查询

五、AQL 语句解释

FOR v IN 1..100 INBOUND "User/669287" RelationShip RETURN v
1..100表示遍历的最小深度为1、最大深度为100, IN min..max 为固定写法,固定语法

更新于 2019年12月17日 12:46
2、 graph数据查询

FOR vertex[, edge[, path]]
IN [min[..max]]
OUTBOUND|INBOUND|ANY startVertex
edgeCollection[, more…]

解释:
FOR 有三个参数
‣ vertex (object): 遍历中的当前顶点
‣ edge (object, optional): 遍历中的当前边
‣ path (object, optional): 两个对象的路径表示

‣ vertices: 此路径上所有顶点的数组

‣ edges: 此路径上所有边的数组

IN min…max: 定义遍历的最小深度和最大深度。如果未指定,默认为1!

OUTBOUND/INBOUND/ANY :定义搜索的方向

edgeCollection: 保存在遍历中要考虑的边缘的集合的一个或多个名称

OPTIONS options(object,optional):用于修改遍历的执行。只有以下属性有效果,所有其他属性将被忽略:

uniqueVertices(string):可选地确保顶点唯一性

“path” - 保证没有路径返回一个重复的顶点

“global” - 保证在遍历期间每个顶点最多被访问一次,无论从起始顶点到这个顶点有多少路径。如果您从最小深度min depth > 1之前发现的顶点开始,可能根本不会返回(它仍然可能是路径的一部分)。注意: 使用此配置,结果不再是确定性的。如果从startVertex到顶点有多条路径,则选择其中一条路径。

“none”(默认) - 不对顶点应用唯一性检查

uniqueEdges(string):可选地确保边缘唯一性

“path”(默认) - 保证没有路径返回一个重复的边

“global” - 保证在遍历过程中,每个边缘最多被访问一次,无论从起始顶点到该边缘有多少条路径。如果从a开始,min depth > 1在最小深度之前发现的边缘根本不会被返回(它仍然可能是路径的一部分)。注意: 使用此配置,结果不再是确定性的。如果有从多个路径startVertex超过边缘的那些中的一个被拾取。

“none” - 不对边缘应用唯一性检查。注意: 使用此配置,遍历将跟随边沿周期。

bfs(bool):可选地使用可选的宽度优先遍历算法

true - 遍历将被执行宽度优先。结果将首先包含深度1的所有顶点。比深度2处的所有顶点等等。

false(默认) - 遍历将以深度优先执行。它首先将深度1的一个顶点的最小深度的最小深度返回到最大深度。对于深度1处的下一个顶点,依此类推。
查询示例:
查所洛杉矶可以直达的所有飞机场

FOR airport IN OUTBOUND 'airports/LAX' flights
    RETURN DISTINCT airport

查所洛杉矶可以直达的所有飞机场,优化AQL语句:

FOR airport IN OUTBOUND 'airports/LAX' flights
OPTIONS {
    
    
bfs:true,
uniqueVertices:'global'}
RETURN airport

这个查询将比上面的使用distict快很多。因为distict是在遍历完所有节点后再去除重复的,而options则可以直接过掉重复的结果不进行遍历。
 
返回10个洛杉矶的航班和他们的目的地,如下AQL语句:

FOR airport, flight IN OUTBOUND 'airports/LAX' flights
    LIMIT 10
    RETURN {
    
    airport, flight}

3、 唯一遍历
对于最小深度大于2的遍历,有两个选项可以选择:

深度优先(默认):继续沿着从起始顶点到该路径上的最后顶点的边缘,或者直到达到最大遍历深度,然后向下走其他路径

广度优先(可选):从开始顶点到下一个级别遵循所有边缘,然后按另一个级别跟踪邻居的所有边缘,并继续这个模式,直到没有更多的边缘跟随或达到最大的遍历深度。

由于不同点之间的路径可能有多条,也可能存在闭环线路
默认情况下,遍历的时候如果path中遇到了相同的edge就会停止遍历;这将可以防止遍历存在绕圈情况,让遍历可以到达最底层节点。
在一个path上可能会出现重复的vertex,除非你明确声明不要重复的点。
示例

FOR v,e,p IN 1..5 OUTBOUND 'vertex/s' edgs
OPTIONS {
    
    
uniqueVertices:'none',
uniqueEdges:'path'
}
RETURN CONCAT_SEPARATOR('->',p.vertices[*]._key)

这个uniqueVertices:‘none’和uniqueEdges:‘path’都是默认设置,不设置也是一样。这样最开是的节点也可以是最后的节点,因为我们在设置的时候并没有要求path中有唯一的点。如果要设置为唯一的,可以也设置为‘path’,这样一条路径中的点也将变为唯一的。

global保证每个点在所有遍历中只出现一次。它仅适用于广度优先。示例

FOR v IN 1..5  OUTBOUND 'vertex/s' edgs
OPTIONS{
    
    
bfs:ture,
uniqueVertices:'global'
RETURN v._key

4、LET关键字

LET可以用来声明变量,来将查询结果赋值给变量。

FOR f IN flights
 FILTER f._from == 'airports/BIS'
 LIMIT 100
 LET h = FLOOR(f.DepTime / 100)
 LET m = f.DepTime % 100
 RETURN {
    
    
     year: f.Year,
     month: f.Month,
     day: f.DayofMonth,
     time: f.DepTime,
     iso: DATE_ISO8601(f.Year, f.Month, f.DayofMonth, h, m)
 }

spring-data-demo中,edge涉及到from,to的,需要使用对象,不能是String,而查询参数需要使用String,这个需要注意
即:

@Edge
public class RelationOf {
    
    
	@Id
	private String id;
	@From
	private UserInfo fromUserInfo;  //不能使用String类型
	@To
	private UserInfo toUserInfo;
}
@Query("FOR v IN ANY SHORTEST_PATH @fromId TO @toId  relationOf return v")
	List<UserInfo> getShortestPath(@Param("fromId") String fromId, @Param("toId") String toId);//查询时候需要使用String类型

ArangoDB 的graph查询
ArangoDB简单实例介绍
ArangoDB 学习笔记 (4)graph
AQL 基本语法&用法
ArangoDB查询语言(AQL) 基本语法&用法
ArangoDB查询语言(AQL) 基本语法&用法
https://www.arangodb.com/docs/stable/aql/data-queries.html
更新于2020年12月06日 10:04 未起床

组合查询:MERGE()
查询顶点元素实体与边中的元素组成的新实体

FOR v,e IN 1 OUTBOUND 'userinfo/23742927' relationOf
return MERGE(v,{
    
    relation:e.relation,show:e.show})

MERGE()方法组合的是实体(即括号中的参数需要是一个实体),v是实体,大括号{}可以形成一个新的实体,relation是e中的元素,但是需要为查询到的e.relation起一个新的名字(我起了相同的名字relation)
https://www.arangodb.com/why-arangodb/sql-aql-comparison/

猜你喜欢

转载自blog.csdn.net/w690333243/article/details/103497010