2015-09-26 2 views
0

У меня есть база данных, включая игры в 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 в списке платформ. Теперь мне нужно выяснить, как захватить полные игровые узлы и отфильтровать этот запрос.

+0

Что делает код выглядеть Neo4jClient как для запроса? –

+0

Вы говорите, что хотите все с отличным названием TitleName & Platform combi - значит ли это, если бы у вас были: «Бог войны/[PS3, PSVITA]» и «God of War/[PSVITA]», вам нужно было бы вернуться обратно? –

+0

В идеале я хотел бы сгруппировать все доступные платформы для игры вместе, но иногда мой импортер данных создает отдельные записи для разных платформ для одной и той же игры. –

ответ

0

Если я правильно вас понимаю, вы хотите выбрать различные узлы по свойству и удалить дубликаты? Если это так, это будет примерно так:

MATCH (game:PSNGame {property:'value'}) RETURN DISTINCT game.property 

Это должно удалить дубликаты и вернуть свой узел по свойству.

+0

Это вернет единственный узел с заданным свойством. Я хотел бы вернуть все узлы PSNGame с отдельной комбинацией TitleName и Platform. Я уточню свой вопрос, чтобы быть более конкретным. –

+0

@CameronTinker Попробуйте удалить '.property' с конца. Это вернет весь узел, в настоящее время находится далеко от компьютера, поэтому он не проверен, но сам синтаксис верен. –

2

попробовать это один:

MATCH (game:PSNGame) 
with game, collect([game.TitleName, game.Platforms]) as wow 
return distinct(wow) 
Смежные вопросы