У меня есть база данных, включая игры в PlayStation, и она содержит игры из всех регионов и платформ. Некоторые игры из разных регионов имеют одинаковый титул и платформу, поэтому я хотел бы отфильтровать «дубликаты». На данный момент у меня нет информации о регионе в каждой игре, поэтому лучшее, что я могу сделать, это отфильтровать по названию игры и платформе.Как выбрать различные узлы графа по свойству
Можно ли выбрать отдельные узлы по свойству? Кажется, я помню, что вы можете возвращать отдельные строки на основе столбца в SQL, но кажется, что Cypher применим не только к целой строке, но не только к определенному столбцу.
Я хотел бы, чтобы добиться чего-то вроде следующего:
MATCH (game:PSNGame) RETURN game WHERE distinct game.TitleName, distinct game.Platforms
выше запрос, если бы они были действительными будут возвращать все узлы PSNGame с отчетливым TITLENAME и Платформы комбинации. Так как вышеупомянутый запрос недействителен Cypher, я попытался вернуть список различных TitleName/Platforms, в которых разные символы применяются к обоим столбцам.
Запроса я для возвращения отчетливого списка TITLENAME/платформы выглядит следующим образом:
MATCH (game:PSNGame) RETURN distinct game.TitleName, game.Platforms
Ответ JSON от Neo4j похож на это:
[["God of War", ["PS3", "PSVITA"]], ["God of War II", ["PS3", "PSVITA"]]]
Проблему я столкнулся заключается в том, что ответ JSON на самом деле не является объектом со свойствами. Это больше массив массивов. Если бы я мог получить ответ скорее как объект, я мог бы десериализоваться без проблем. Я попытался десериализоваться как IList<PsnGame>
, но не имел большой удачи.
Вот мои ПОК для IList<PsnGame>
реализации:
public class PsnGame
{
public string TitleName { get; set; }
public string[] Platforms { get; set; }
}
EDIT: Вот простейший пример моего Neo4jClient запроса:
// helper function for handling searching by name and platform
private ICypherFluentQuery BuildPSNGamesQuery(string gameName, string platform)
{
var query = client.Cypher
.Match("(g:PSNGame)");
if (!string.IsNullOrWhiteSpace(gameName))
{
query = query.Where($"g.TitleName =~ \"(?i).*{gameName}.*\"");
if (!string.IsNullOrWhiteSpace(platform) && platform.ToLower() != "all")
{
query = query.AndWhere($"\"{platform}\" in g.Platforms");
}
}
else
{
if (!string.IsNullOrWhiteSpace(platform) && platform.ToLower() != "all")
{
query = query.Where($"\"{platform}\" in g.Platforms");
}
}
return query;
}
Четких игр:
var distinctGames = await BuildPSNGamesQuery(gameName, platform)
.With("DISTINCT g.TitleName AS TitleName, g.Platforms AS Platforms")
.With("{ TitleName: TitleName, Platforms: Platforms } as Games")
.OrderBy("TitleName")
.Return<PsnGame>("Games")
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
.ResultsAsync;
Все игры (как-то нужно отфильтровать на основе предыдущего запроса):
var results = await BuildPSNGamesQuery(gameName, platform)
.Return(g => new Models.PSN.Composite.PsnGame
{
Game = g.As<PsnGame>()
})
.OrderBy("g.TitleName")
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
.ResultsAsync;
Используя карту, я могу вернуть TITLENAME/Platforms спаривание, что я хочу, но я подозреваю, что нужно сделать collect
на платформах, чтобы получить все платформы для конкретного названия игры , Затем я могу отфильтровать весь список игр с помощью отличных игр, которые я возвращаю. Однако я бы предпочел выполнить запрос и объединить запросы для уменьшения HTTP-трафика.
Пример дублей можно увидеть на моем сайте здесь: https://www.gamerfootprint.com/#/games/ps
Кроме того, данные для дублей выглядит примерно так:
MATCH (n:PSNGame)
WHERE n.TitleName = '1001 Spikes'
RETURN n.TitleName, n.Platforms LIMIT 25
JSON:
{
"columns":[
"n.TitleName",
"n.Platforms"
],
"data":[
{
"row":[
"1001 Spikes",
[
"PSVITA"
]
],
"graph":{
"nodes":[
],
"relationships":[
]
}
},
{
"row":[
"1001 Spikes",
[
"PS4"
]
],
"graph":{
"nodes":[
],
"relationships":[
]
}
}
],
"stats":{
"contains_updates":false,
"nodes_created":0,
"nodes_deleted":0,
"properties_set":0,
"relationships_created":0,
"relationship_deleted":0,
"labels_added":0,
"labels_removed":0,
"indexes_added":0,
"indexes_removed":0,
"constraints_added":0,
"constraints_removed":0
}
}
EDIT : 10-31-15
Мне удалось получить отличное название игры и платформы, возвращающиеся с платформы для каждой игры сворачиваются в одну коллекцию. Мой новый запрос следующим образом:
MATCH (game:PSNGame)
WITH DISTINCT game.TitleName as TitleName,
game.Platforms as coll UNWIND coll as Platforms
WITH TitleName as TitleName, COLLECT(DISTINCT Platforms) as Platforms
RETURN TitleName, Platforms
ORDER BY TitleName
Вот небольшая часть результатов:
{
"columns":[
"TitleName",
"Platforms"
],
"data":[
{
"row":[
"1001 Spikes",
[
"PSVITA",
"PS4"
]
],
"graph":{
"nodes":[
],
"relationships":[
]
}
}
],
"stats":{
"contains_updates":false,
"nodes_created":0,
"nodes_deleted":0,
"properties_set":0,
"relationships_created":0,
"relationship_deleted":0,
"labels_added":0,
"labels_removed":0,
"indexes_added":0,
"indexes_removed":0,
"constraints_added":0,
"constraints_removed":0
}
}
Наконец, 1001 Колосья в списке один раз и имеет как PS VITA и PS4 в списке платформ. Теперь мне нужно выяснить, как захватить полные игровые узлы и отфильтровать этот запрос.
Что делает код выглядеть Neo4jClient как для запроса? –
Вы говорите, что хотите все с отличным названием TitleName & Platform combi - значит ли это, если бы у вас были: «Бог войны/[PS3, PSVITA]» и «God of War/[PSVITA]», вам нужно было бы вернуться обратно? –
В идеале я хотел бы сгруппировать все доступные платформы для игры вместе, но иногда мой импортер данных создает отдельные записи для разных платформ для одной и той же игры. –