我有一个类似于此的图表:
(t:Teacher)-[:TEACHES]-(s:Student)-[:ATTENDS]-(s:Subject)-[:REQUIRES]-(b:Book)
以@NodeEntity
类表示。
我需要为具有给定范围的ID的教师加载所有@NodeEntities
,并在一个查询中获取他们所教授的所有学生,以及每个科目所需的科目和书籍。
我试过
int depth=3;
List<Long> ids = newArrayList(3,4,5);
session.loadAll(Teacher.class, ids, depth);
我实际上是从相应的GraphRepository
findAll
开始的,这是一回事。
不幸的是,我得到了数据库中所有可用教师的列表,因为每个学生都是由所有教师教授的。我也试过运行自定义@Query,虽然看起来你不能指定自定义深度How to control depth on custom Spring Data Neo4j repository methods?,也不能从自定义密码查询中返回多个节点。
你知道为什么我的做法错了吗?这个接缝是对neo4j的一个简单使用,我一直在抓取整个图形。
答案 0 :(得分:0)
是的,当您使用模型将//#define _USE_NT_VERSION_
class SPYDATA :
#ifdef _USE_NT_VERSION_
IO_STATUS_BLOCK
#else
OVERLAPPED
#endif
{
HANDLE _hFile;
LONG _dwRef;
union {
FILE_NOTIFY_INFORMATION _fni;
UCHAR _buf[PAGE_SIZE];
};
void DumpDirectoryChanges()
{
union {
PVOID buf;
PBYTE pb;
PFILE_NOTIFY_INFORMATION pfni;
};
buf = _buf;
for (;;)
{
DbgPrint("%x <%.*S>\n", pfni->Action, pfni->FileNameLength >> 1, pfni->FileName);
ULONG NextEntryOffset = pfni->NextEntryOffset;
if (!NextEntryOffset)
{
break;
}
pb += NextEntryOffset;
}
}
#ifdef _USE_NT_VERSION_
static VOID WINAPI _OvCompRoutine(
_In_ NTSTATUS dwErrorCode,
_In_ ULONG_PTR dwNumberOfBytesTransfered,
_Inout_ PIO_STATUS_BLOCK Iosb
)
{
static_cast<SPYDATA*>(Iosb)->OvCompRoutine(dwErrorCode, (ULONG)dwNumberOfBytesTransfered);
}
#else
static VOID WINAPI _OvCompRoutine(
_In_ DWORD dwErrorCode, // really this is NTSTATUS
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
)
{
static_cast<SPYDATA*>(lpOverlapped)->OvCompRoutine(dwErrorCode, dwNumberOfBytesTransfered);
}
#endif
VOID OvCompRoutine(NTSTATUS status, DWORD dwNumberOfBytesTransfered)
{
DbgPrint("[%x,%x]\n", status, dwNumberOfBytesTransfered);
if (0 <= status)
{
if (status != STATUS_NOTIFY_CLEANUP)
{
if (dwNumberOfBytesTransfered) DumpDirectoryChanges();
process_list_of_existing_files();// so hard do this here ?!?
DoRead();
}
else
{
DbgPrint("\n---- NOTIFY_CLEANUP -----\n");
}
}
Release();
MyReleaseRundownProtection();
}
~SPYDATA()
{
Cancel();
}
public:
void DoRead()
{
if (MyAcquireRundownProtection())
{
AddRef();
#ifdef _USE_NT_VERSION_
NTSTATUS status = ZwNotifyChangeDirectoryFile(_hFile, 0, 0, this, this, &_fni, sizeof(_buf), FILE_NOTIFY_VALID_MASK, TRUE);
if (NT_ERROR(status))
{
OvCompRoutine(status, 0);
}
#else
if (!ReadDirectoryChangesW(_hFile, _buf, sizeof(_buf), TRUE, FILE_NOTIFY_VALID_MASK, (PDWORD)&InternalHigh, this, 0))
{
OvCompRoutine(RtlGetLastNtStatus(), 0);
}
#endif
}
}
SPYDATA()
{
_hFile = 0;// ! not INVALID_HANDLE_VALUE because use ntapi for open file
_dwRef = 1;
#ifndef _USE_NT_VERSION_
RtlZeroMemory(static_cast<OVERLAPPED*>(this), sizeof(OVERLAPPED));
#endif
}
void AddRef()
{
InterlockedIncrement(&_dwRef);
}
void Release()
{
if (!InterlockedDecrement(&_dwRef))
{
delete this;
}
}
BOOL Create(POBJECT_ATTRIBUTES poa)
{
IO_STATUS_BLOCK iosb;
NTSTATUS status = ZwOpenFile(&_hFile, FILE_GENERIC_READ, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE);
if (0 <= status)
{
return
#ifdef _USE_NT_VERSION_
0 <= RtlSetIoCompletionCallback(_hFile, _OvCompRoutine, 0);
#else
BindIoCompletionCallback(_hFile, _OvCompRoutine, 0);
#endif
}
return FALSE;
}
void Cancel()
{
if (HANDLE hFile = InterlockedExchangePointer(&_hFile, 0))
{
NtClose(hFile);
}
}
};
void DemoF()
{
if (MyInitializeRundownProtection())
{
STATIC_OBJECT_ATTRIBUTES(oa, "<SOME_DIRECTORY>");
if (SPYDATA* p = new SPYDATA)
{
if (p->Create(&oa))
{
p->DoRead();
}
//++ GUI thread run
MessageBoxW(0, L"wait close program...", L"", MB_OK);
//-- GUI thread end
p->Cancel();
p->Release();
}
MyWaitForRundownProtectionRelease();
}
}
调用到深度3时,您基本上会返回所有教师,因为没有应用于加载查询的模式匹配将其限制为您正在谈论的节点。因此,从深度的角度考虑这个问题并不能真正帮助你做什么。
有两种(虽然类似)方法可以实现这一目标。
a)您正确地提到使用自定义session.loadAll
。这是最简单的方法,您无需指定深度。为了使查询正常工作,您必须也返回您的关系。你的签名是这样的:
@Query
b)您可以使用 @Query("MATCH (t:Teacher)-[teacherRels:TEACHES]-(st:Student)-[studentRels:ATTENDS]-(su:Subject)-[subjectRels:REQUIRES]-(b:Book) WHERE ID(t) in {ids} RETURN t, teacherRels, st, studentRels, su, subjectRels, b")
public Iterable<Teacher> findTeachersByIds(@Param("ids") List<Long> ids);
执行与上述相同的操作(这是上述方法基本上会调用的内容)。
如果你想升级,你应该使用session.query
,这应该在2016年11月28日发布(如果你愿意,可以同时使用4.2.0.RC1
。它比{{更稳定} 1}})。